Neato Connected support

I just found a python API which gives access to the neato Connected vaccum so we could launch directly from home-assistant: https://github.com/stianaske/pybotvac

If anyone wants to implement it, i don’t think it should be a big challenge, otherwise I’ll do it once I finish my work for the Netatmo Welcome camera

I don’t have the ability to implement. But id be more than happy to test if required.

Hi All,

I plan to start the development of this feature soon, is there something that you want in priority. For the first release, I plan to do something really simple, just a switch which will start cleaning if turn on, and return to Dock if turn OFF

1 Like

That’s great news @jabesq :slight_smile: it would be cool to have battery life and current status implemented. But I’m sure I’m not alone in saying I’d be hugely greatful just having the switch.

As I said before I can’t contribute with code but if there is anything I could help with please let me know.

hi all,

switch is indeed a “must-have” if we implement this kind of device.
The status “working/in charge/blocked” should be a good “nice to have” I think.

If you need help, i can do my best (which is a little… but better than nothing)

Hi all,

the first draft for this component is available here: https://github.com/jabesq/home-assistant/blob/02a268c9ba1b4cdd2a785d17030f97e073cfb4c8/homeassistant/components/switch/neato.py.

You can try it by putting it inside <config_directory>/custom_components/switch/

To enable it the configuration in your configuration.yaml is the following one:
switch:
platform: neato
username:
password:

This will add a switch which will start a full home cleaning when turning ON and send the robot back to base when turning OFF

PS: This currently a beta, and I have experienced a crash of home-assistant last night (don’t know yet if this is related) but use this at your own risk

Hi,

I installed your script, will see next hours if it crashs my HA.

Do you have a look to https://developers.neatorobotics.com/api/ ?
seems to be easier to get data and send command to neato robot.

I just add a look to your script (in the zip) and you seems to use that doc but it was just in case :slight_smile:

No, I did not use https://developers.neatorobotics.com/api/ because I did not know it was existing, I think it’s quite a new website.

I used python API which was created by someone else (https://github.com/stianaske/pybotvac) using reverse engineering, but I check this website to see if I can improve this API (which is currently doing the job fine)

Extra information about my component, it has been tested only with a Neato Connected but not with the Neato botvac D3 and D5 (as I don’t have them)

Thanks @jabesq I’ve just added the component and its working for me on my Neato Botvac Connected will report back any crashing.

Hi,

just like to conform, for me, it is not working with botvac d3.

I take a look at the API-Documentation and found a way to get my D3 working with the existing Component, after editing the robot.py

Just read a little bit in the API-Documentation.

Heres my Code. Just had to adopt some JSON-Calls

import requests
import hmac
import time
import os.path

# Disable warning due to SubjectAltNameWarning in certificate
requests.packages.urllib3.disable_warnings()


class Robot:
    """Data and methods for interacting with a Neato Botvac Connected vacuum robot"""

    def __init__(self, serial, secret, name=''):
        """
        Initialize robot

        :param serial: Robot serial
        :param secret: Robot secret
        :param name: Name of robot (optional)
        """
        self.name = name
        self.serial = serial
        self.secret = secret

        self._url = 'https://nucleo.neatocloud.com/vendors/neato/robots/{}/messages'.format(self.serial)
        self._headers = {'Accept': 'application/vnd.neato.nucleo.v1'}

    def __str__(self):
        return "Name: %s, Serial: %s, Secret: %s" % (self.name, self.serial, self.secret)

    def _message(self, json):
        """
        Sends message to robot with data from parameter 'json'
        :param json: dict containing data to send
        :return: server response
        """

        cert_path = os.path.join(os.path.dirname(__file__), 'cert', 'neatocloud.com.crt')
        response = requests.post(self._url,
                                 json=json,
                                 verify=cert_path,
                                 auth=Auth(self.serial, self.secret),
                                 headers=self._headers)
        response.raise_for_status()
        return response

    def start_cleaning(self):
        json = {'reqId': "1",
                'cmd': "startCleaning",
                'params': {
                    'category': 2,
                    'navigationMode': 2}
                }
        return self._message(json)

    def pause_cleaning(self):
        return self._message({'reqId': "77", 'cmd': "pauseCleaning"})

    def resume_cleaning(self):
        return self._message({'reqId': "77", 'cmd': "resumeCleaning"})

    def stop_cleaning(self):
        return self._message({'reqId': "77", 'cmd': "stopCleaning"})

    def send_to_base(self):
        return self._message({'reqId': "77", 'cmd': "sendToBase"})

    def get_robot_state(self):
        return self._message({'reqId': "1", 'cmd': "getRobotState"})

    def enable_schedule(self):
        return self._message({'reqId': "1", 'cmd': "enableSchedule"})

    def disable_schedule(self):
        return self._message({'reqId': "1", 'cmd': "disableSchedule"})

    def get_schedule(self):
        return self._message({'reqId': "1", 'cmd': "getSchedule"})

    @property
    def schedule_enabled(self):
        return self.get_robot_state().json()['details']['isScheduleEnabled']

    @schedule_enabled.setter
    def schedule_enabled(self, enable):
        if enable:
            self.enable_schedule()
        else:
            self.disable_schedule()

    @property
    def state(self):
        return self.get_robot_state().json()


class Auth(requests.auth.AuthBase):
    """Create headers for request authentication"""

    def __init__(self, serial, secret):
        self.serial = serial
        self.secret = secret

    def __call__(self, request):
        date = time.strftime('%a, %d %h %Y %H:%M:%S', time.gmtime()) + ' GMT'

        signing = hmac.new(key=self.secret.encode('utf8'),
                           msg='\n'.join([self.serial.lower(), date, request.body.decode('utf8')]).encode('utf8'),
                           digestmod='sha256')

        request.headers['Date'] = date
        request.headers['Authorization'] = "NEATOAPP " + signing.hexdigest()

        return request

Any Chance to implement this to the existing Component? Or can someone with an older connected Model if this also works?

BR

Lukas

When I launch my HA, I get the following error :

Feb 13 10:48:20 raspberrypi hass[2008]: INFO:homeassistant.loader:Loaded switch.neato from homeassistant.components.switch.neato
Feb 13 10:48:20 raspberrypi hass[2008]: INFO:homeassistant.bootstrap:Setting up switch
Feb 13 10:48:20 raspberrypi hass[2008]: INFO:homeassistant.components.switch:Setting up switch.neato
Feb 13 10:48:20 raspberrypi hass[2008]: ERROR:homeassistant.components.switch:Error while setting up platform neato
Feb 13 10:48:20 raspberrypi hass[2008]: Traceback (most recent call last):
Feb 13 10:48:20 raspberrypi hass[2008]: File “/srv/homeassistant/homeassistant_venv/lib/python3.4/site-packages/homeassistant/helpers/entity_component.py”, line 151, in _async_setup_platform
Feb 13 10:48:20 raspberrypi hass[2008]: entity_platform.add_entities, discovery_info
Feb 13 10:48:20 raspberrypi hass[2008]: File “/usr/lib/python3.4/asyncio/futures.py”, line 388, in iter
Feb 13 10:48:20 raspberrypi hass[2008]: yield self # This tells Task to wait for completion.
Feb 13 10:48:20 raspberrypi hass[2008]: File “/usr/lib/python3.4/asyncio/tasks.py”, line 286, in _wakeup
Feb 13 10:48:20 raspberrypi hass[2008]: value = future.result()
Feb 13 10:48:20 raspberrypi hass[2008]: File “/usr/lib/python3.4/asyncio/futures.py”, line 277, in result
Feb 13 10:48:20 raspberrypi hass[2008]: raise self._exception
Feb 13 10:48:20 raspberrypi hass[2008]: File “/usr/lib/python3.4/concurrent/futures/thread.py”, line 54, in run
Feb 13 10:48:20 raspberrypi hass[2008]: result = self.fn(*self.args, **self.kwargs)
Feb 13 10:48:20 raspberrypi hass[2008]: File “/srv/homeassistant/homeassistant_venv/lib/python3.4/site-packages/homeassistant/components/switch/neato.py”, line 26, in setup_platform
Feb 13 10:48:20 raspberrypi hass[2008]: if not hass.data[NEATO_ROBOTS]:
Feb 13 10:48:20 raspberrypi hass[2008]: KeyError: ‘neato_robots’

Hi,

do you mean with my Changes?

For me its working well, i also see some errors in the Logs regarding the Neato Platform, but seems not to affect the Component or HA.

not tried your change… i’ve a connected botvac, not a D3

1 Like

Hi
I’m new to the HA part of the automation world but I have searched for a way to integrate my Botvac D5 to my home system so that it automatically shuts off some z-wave motion sensors when the bot starts cleaning when I’m not at home and everything is armed.
Hopefully this will work =)

When I get everything set up I will test and see if this works with the D5 but I vote for a solution for the Neato component to be upgraded for all their connected models.

1 Like

Tested your robot.py and it works great with my D5.
How can we get the original Neato-component to be upgraded?

1 Like

Hi @runevad great to here it’s working for you. Since I’m not a developer I don’t really now how to do that. Maybe i have some time next wekk to investigate.

So long

Lukas

1 Like

@jabesq Now when the new “vacum”-component is implemented in version 0.5x it would be nice to see all of the connected series (Connected, D3 and D5) added as well.

I will look into the Neato API but I’m not a very good programmer and as @outrun said I have no idea of how to get this into the new vacum-component…

Anyone else out there, wanting to implement their Neato Botvac that could help?

1 Like

I would love if we could get Neato support. Now with the vacum component, i’ll hope this is something that could be done.

Realise I’m jumping into an old threat but wanted to add to this discussion a request for support for the Kobold VR200 - basically a rebadged Neato. I’ve managed to find a Node script that I can get talking to it but my attempts to modify the existing Neato component have fallen flat.

Is the Neato component currently working for people who have a Neato (original - not even D3 or D5)?