Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot (really) control Roomba 980 #128

Open
Rafsisa opened this issue May 30, 2024 · 2 comments
Open

Cannot (really) control Roomba 980 #128

Rafsisa opened this issue May 30, 2024 · 2 comments

Comments

@Rafsisa
Copy link

Rafsisa commented May 30, 2024

Hi!

I'm working with the current script:

import asyncio
from roomba import Roomba

async def test():
        await roomba.connect()
        roomba.send_command('start')
        await asyncio.sleep(5)
        roomba.send_command('stop')
        roomba.send_command('dock')
        await roomba.disconnect()

roomba = Roomba('172.17.23.104')
loop = asyncio.get_event_loop()
loop.run_until_complete(test())

This indeed starts the Roomba 980 at 172.17.23.104, but that's the last thing that works. The vacuum never stops or docks as it should. The output of this script is as follows:

Pending event queue size is: 1
Pending event queue size is: 1
/home/user/src/Roomba980-Python/roomba/roomba.py:607: RuntimeWarning: coroutine 'Roomba._disconnect' was never awaited
  self.loop.create_task(self._disconnect())
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
Task exception was never retrieved
future: <Task finished name='Task-26' coro=<Roomba._disconnect() done, defined at /home/user/src/Roomba980-Python/roomba/roomba.py:609> exception=AttributeError("type object '_asyncio.Task' has no attribute 'all_tasks'")>
Traceback (most recent call last):
  File "/home/user/src/Roomba980-Python/roomba/roomba.py", line 612, in _disconnect
    tasks = [t for t in asyncio.Task.all_tasks() if t is not asyncio.Task.current_task()]
                        ^^^^^^^^^^^^^^^^^^^^^^
AttributeError: type object '_asyncio.Task' has no attribute 'all_tasks'
Traceback (most recent call last):
  File "/home/user/src/Roomba980-Python/roomba/./test.py", line 16, in <module>
    loop.run_until_complete(test())
  File "/usr/lib/python3.12/asyncio/base_events.py", line 687, in run_until_complete
    return future.result()
           ^^^^^^^^^^^^^^^
  File "/home/user/src/Roomba980-Python/roomba/./test.py", line 12, in test
    await roomba.disconnect()
TypeError: object NoneType can't be used in 'await' expression
@NickWaterton
Copy link
Owner

You don’t seem to know how asyncio works.

roomba.connect() and roomba.disconnect() are not async methods.

@Rafsisa
Copy link
Author

Rafsisa commented Jun 4, 2024

Sorry, I was a bit exhausted then...

I'm now using this wrapper class:

import asyncio
import roomba as wrapped

loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
lruc = loop.run_until_complete

class Roomba980:
	def __init__(self, *args, **kwargs):
		self._roomba = wrapped.Roomba(*args, **kwargs)
	def connect(self):
		return lruc(self._connect_async())
	def disconnect(self):
		return self._roomba.disconnect()
	def start(self):
		lruc(self._command_async('start', 15))
	def stop(self):
		lruc(self._command_async('stop'))
	def dock(self):
		lruc(self._command_async('dock'))
	@property
	def phase(self):
		return self._get_prop('phase')
	@property
	def current_state(self):
		return self._get_prop('current_state')
	@property
	def sku(self):
		return self._get_prop('sku')
	async def _connect_async(self):
		return await self._roomba.connect()
	async def _command_async(self, cmd, sleep=5):
		self._roomba.send_command(cmd)
		await asyncio.sleep(sleep)
	def _get_prop(self, name):
		return self._roomba.get_property(name)

roomba = Roomba980('172.17.23.104')
roomba.connect()
print('connected')

roomba.start()
print('started')
roomba.stop()
print('stopped')
roomba.dock()
print('docked')

print('phase        : %r'%roomba.phase)
print('current_state: %r'%roomba.current_state)
print('sku          : %r'%roomba.sku)

roomba.disconnect()
print('disconnected')

The properties (phase, current_state and sku) are None when run without the start-stop-dock code. Is that the case with your Roomba too?
Also sometimes the connection is lost after successfully stopping of the Roomba (printing 'Unexpected Disconnect! - reconnecting') and docking is omitted. In some cases, this still succeeds after the 'Unexpected Disconnect'. How can I handle or even fix that?

Besides that, since I'm running Python 3.12.3 I had to modify roomba.py:

diff --git a/roomba/roomba.py b/roomba/roomba.py
index 09da3bf..4a6c021 100755
--- a/roomba/roomba.py
+++ b/roomba/roomba.py
@@ -609,7 +609,7 @@ class Roomba(object):
     async def _disconnect(self):
         #if self.ws:
         #    await self.ws.cancel()
-        tasks = [t for t in asyncio.Task.all_tasks() if t is not asyncio.Task.current_task()]
+        tasks = [t for t in asyncio.all_tasks(asyncio.get_event_loop()) if t is not asyncio.current_task()]
         [task.cancel() for task in tasks]
         self.log.info("Cancelling {} outstanding tasks".format(len(tasks)))
         await asyncio.gather(*tasks, return_exceptions=True)

Thank you for maintainig this module!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants