diff --git a/sucks/__init__.py b/sucks/__init__.py
index 55977fd..3ce82ca 100644
--- a/sucks/__init__.py
+++ b/sucks/__init__.py
@@ -416,9 +416,14 @@ class VacBot():
getattr(self, method)(ctl)
def _handle_error(self, event):
- error = event['error']
- self.errorEvents.notify(error)
- _LOGGER.debug("*** error = " + error)
+ if 'error' in event:
+ error = event['error']
+ elif 'errs' in event:
+ error = event['errs']
+
+ if not error == '':
+ self.errorEvents.notify(error)
+ _LOGGER.debug("*** error = " + error)
def _handle_life_span(self, event):
type = event['type']
@@ -483,6 +488,10 @@ class VacBot():
elif 'errno' in event: #Handle error
if event['ret'] == 'fail' and event['errno'] == '8': #Already charging
status = 'slot_charging'
+ elif event['ret'] == 'fail' and event['errno'] == '5': #Busy with another command
+ status = 'idle'
+ elif event['ret'] == 'fail' and event['errno'] == '3': #Bot in stuck state, example dust bin out
+ status = 'idle'
else:
status = 'idle' #Fall back to Idle status
_LOGGER.error("Unknown charging status '" + event['errno'] + "'") #Log this so we can identify more errors
@@ -632,7 +641,9 @@ class EcoVacsIOT():
action.args['clean']['act'] = CLEAN_ACTION_TO_ECOVACS['start'] #Inject a start action
c = self._wrap_command(action, recipient)
_LOGGER.debug('Sending command {0}'.format(c))
- self._handle_ctl(action, self.api._EcoVacsAPI__call_portal_api(self.api, self.api.IOTDEVMANAGERAPI,'',c ))
+ self._handle_ctl(action,
+ self.api._EcoVacsAPI__call_portal_api(self.api, self.api.IOTDEVMANAGERAPI,'',c )
+ )
def _wrap_command(self, cmd, recipient):
diff --git a/tests/test_ecovacs_iot.py b/tests/test_ecovacs_iot.py
index 9f4ec1b..04c2604 100644
--- a/tests/test_ecovacs_iot.py
+++ b/tests/test_ecovacs_iot.py
@@ -1,15 +1,21 @@
from re import compile
import requests_mock
+import requests
from nose.tools import *
from sucks import *
-from test_ecovacs_api import make_api
+from tests.test_ecovacs_api import make_api
# There are few tests for the IOT stuff here because it's relatively complicated to test given
# the library's design and its multithreaded nature and lack of explicit testing support.
+
+def test_is_iot():
+ x = make_ecovacs_iot()
+ assert_equal(x.vacuum['iot'], True)
+
def test_wrap_command():
x = make_ecovacs_iot()
@@ -18,52 +24,81 @@ def test_wrap_command():
assert_equal(c['toId'], 'E0000000001234567890')
assert_equal(c['payload'], '')
-def test_is_iot():
+def test_iotapi_response():
x = make_ecovacs_iot()
-
-# TODO - Error response from command
-#'cmdName': 'Charge', 'payload': '', 'payloadType': 'x', 'td': 'q', 'toId': '0e084f6c-0846-4342-a947-fe14c293301f', 'toRes': 'wC3g', 'toType': 'ls1ok3'}
-# - Already charging on dock
-#{'ret': 'ok', 'resp': "", 'id': 'NLQy'}
-
-#Timeout
-# {'ret': 'fail', 'errno': 500, 'debug': 'wait for response timed out'}
-
-# def test_subscribe_to_ctls():
-# response = None
-
-# def save_response(value):
-# nonlocal response
-# response = value
-
-# x = make_ecovacs_iot()
-
-# query = x.make_iq_query()
-# query.set_payload(
-# ET.fromstring(' '))
-
-# x.subscribe_to_ctls(save_response)
-# x._handle_ctl(query)
-# assert_dict_equal(response, {'event': 'clean_report', 'type': 'auto'})
+ api = make_api()
+ x.api = api
+
+ with requests_mock.mock() as m:
+
+ #Test GetCleanState
+ resp = {"ret":"ok","resp":"","id":"Qgxa"}
+ r1 = m.post(compile('iot/devmanager.do'),
+ json=resp)
+ cmd = VacBotCommand("GetCleanState")
+ c = x._wrap_command(cmd, x.vacuum['did'])
+ rtnval = api._EcoVacsAPI__call_portal_api(api.IOTDEVMANAGERAPI, '', c)
+ assert_equal(rtnval, {'ret':'ok','resp':"",'id':'Qgxa'})
+
+ #Test Timeout
+ r2 = m.post(compile('iot/devmanager.do'),exc=requests.exceptions.ReadTimeout)
+ cmd = VacBotCommand("GetCleanState")
+ c = x._wrap_command(cmd, x.vacuum['did'])
+ rtnval = api._EcoVacsAPI__call_portal_api(api.IOTDEVMANAGERAPI, '', c)
+ assert_equal(rtnval, {}) #Right now it sends back a blank object
-# def test_xml_to_dict():
-# x = make_ecovacs_iot()
+def test_subscribe_to_ctls():
+ response = None
-# assert_dict_equal(
-# x._ctl_to_dict(make_ctl(' ')),
-# {'event': 'clean_report', 'type': 'auto'})
-# assert_dict_equal(
-# x._ctl_to_dict(make_ctl(' ')),
-# {'event': 'clean_report', 'type': 'auto', 'speed': 'strong'})
+ def save_response(value):
+ nonlocal response
+ response = value
-# assert_dict_equal(
-# x._ctl_to_dict(make_ctl('')),
-# {'event': 'battery_info', 'power': '095'})
+ x = make_ecovacs_iot()
+
+ x.subscribe_to_ctls(save_response)
+ message = {}
+ message['resp'] = ' '
+
+ x.subscribe_to_ctls(save_response)
+ x._handle_ctl("Clean", message)
+ assert_dict_equal(response, {'event': 'clean_report', 'type': 'auto'})
-# assert_dict_equal(
-# x._ctl_to_dict(make_ctl('# ')),
-# {'event': 'life_span', 'type': 'brush', 'val': '099', 'total': '365'})
+
+def test_xml_to_dict():
+ x = make_ecovacs_iot()
+ message = {}
+
+ cmd = VacBotCommand("Clean")
+ message['resp'] = ""
+ assert_dict_equal(
+ x._ctl_to_dict(cmd,message['resp']),
+ {'event': 'clean_report', 'type': 'auto', 'speed': 'standard', 'st':'h','t':'1159','a':'15','s':'0','tr':''})
+
+ cmd = VacBotCommand("Clean")
+ message['resp'] = ""
+ assert_dict_equal(
+ x._ctl_to_dict(cmd,message['resp']),
+ {'event': 'clean_report', 'type': 'auto', 'speed': 'strong', 'st':'h','t':'1159','a':'15','s':'0','tr':''})
+
+ cmd = VacBotCommand("GetBatteryInfo")
+ message['resp'] = ""
+ assert_dict_equal(
+ x._ctl_to_dict(cmd,message['resp']),
+ {'event': 'battery_info', 'power': '82'})
+
+ cmd = VacBotCommand("GetLifeSpan")
+ message['resp'] = ""
+ assert_dict_equal(
+ x._ctl_to_dict(cmd,message['resp']),
+ {'event': 'life_span','ret':'ok', 'type': 'brush', 'left': '9876', 'total': '18000'})
+
+ cmd = VacBotCommand("Charge")
+ message['resp'] = ""
+ assert_dict_equal(
+ x._ctl_to_dict(cmd,message['resp']),
+ {'event': 'charge_state','ret':'fail', 'errno': '8'}) #Test fail from charge command
def make_ecovacs_iot():
diff --git a/tests/test_vacbot.py b/tests/test_vacbot.py
index 3276767..77a9331 100644
--- a/tests/test_vacbot.py
+++ b/tests/test_vacbot.py
@@ -45,10 +45,16 @@ def test_handle_charge_state():
v._handle_ctl({'event': 'charge_state', 'type': 'idle'})
assert_equals('idle', v.charge_status)
- v._handle_ctl({'event': 'charge_state', 'ret': 'fail', 'errno': '8'}) #Seen in IOT when already charging
+ v._handle_ctl({'event': 'charge_state', 'ret': 'fail', 'errno': '9'}) #Seen in IOT - "but on charger, but turned off"
+ assert_equals('idle', v.charge_status)
+
+ v._handle_ctl({'event': 'charge_state', 'ret': 'fail', 'errno': '8'}) #Seen in IOT - could be "already charging"
assert_equals('charging', v.charge_status)
- v._handle_ctl({'event': 'charge_state', 'ret': 'fail', 'errno': '5'}) #Seen in IOT randomly - not sure what this is yet
+ v._handle_ctl({'event': 'charge_state', 'ret': 'fail', 'errno': '5'}) #Seen in IOT - could be "busy with another command"
+ assert_equals('idle', v.charge_status)
+
+ v._handle_ctl({'event': 'charge_state', 'ret': 'fail', 'errno': '3'}) #Seen in IOT - could be "Bot in stuck state, example dust bin out"
assert_equals('idle', v.charge_status)
v._handle_ctl({'event': 'charge_state', 'type': 'a_type_not_supported_by_sucks'})
@@ -87,6 +93,14 @@ def test_handle_battery_info():
v._handle_ctl({'event': 'battery_info', 'power': '000'})
assert_equals(0.0, v.battery_status)
+
+def test_handle_geterrors():
+ v = a_vacbot()
+
+ #v._handle_error
+
+ #ssert_equals({}, v.components)
+
def test_lifespan_reports():
v = a_vacbot()
assert_equals({}, v.components)
@@ -139,6 +153,9 @@ def test_is_charging():
v._handle_ctl({'event': 'clean_report', 'type': 'edge', 'speed': 'normal'})
assert_false(v.is_charging)
+
+
+
def test_send_ping_no_monitor():
#Test XMPP Ping
v = a_vacbot()