Issue with Neato botvac zones

I’m having issues with my Neato botvac D7, and its integration with Home Assistant. Since it frequently reports not recognizing the environment, I started using zones. The zones I use cover the entire floor, and seems to be a workaround for when it doesn’t recognize which floor it is on. I have created two zones, one for each floor:

and

If I then use these zones to “Call Service” in the “Developer Tools”, for service “neato.custom_cleaning”, with the data

entity_id: vacuum.dammaren
zone: entrylevel

Then it works fine. However, if I change from “entrylevel” to “secondlevel”. Then I get an error message in home-assistant.log

Zone ‘secondlevel’ was not found for the robot ‘Dammaren’

I then received some help on github on how to check in more detail which maps/zones are available. I issued the following command:

import pybotvac
account = pybotvac.Account('username', 'password')
account.refresh_robots()
print(account.persistent_maps)
for robot in pybotvac.Account('username', 'password').robots:print(robot)
  boundary = robot.get_map_boundaries('plan1').json()
  print ("Boundary for plan1",boundary)
  boundary = robot.get_map_boundaries('plan2').json()
  print ("Boundary for plan2",boundary)

This obviously produced alot of text, I will cut most of it. Hopefully I kept the relevant part. The first part shows that I have two “persistant maps”, named “plan1” and “plan2”. So far so good. Then for the next part when I want to check the zones (or I think that’s what I’m doing).

Boundary for plan1 
{
	'version': 1, 'reqId': '1', 'result': 'not_found', 'data': {}, 'error': None, 
	'alert': None, 'state': 1, 'action': 0, 'cleaning': 
		{
			'category': 4, 'mode': 2, 'modifier': 1, 'navigationMode': 1, 'mapId': '', 'spotWidth': 0, 'spotHeight': 0
		}, 
	'details': 
		{
			'isCharging': False, 'isDocked': True, 'isScheduleEnabled': False,'dockHasBeenSeen': False,'charge': 95
		}, 
	'availableCommands': 
		{
			'start': True, 'stop': False, 'pause': False,'resume': False,'goToBase': False
		}, 
	'availableServices': 
		{
			'findMe': 'basic-1','generalInfo': 'basic-1','houseCleaning': 'basic-4','IECTest': 'advanced-1','logCopy': 'basic-1',
			'manualCleaning': 'basic-1','maps': 'basic-2','preferences': 'basic-2','schedule': 'basic-2','softwareUpdate': 'basic-1',
			'spotCleaning': 'basic-3','wifi': 'basic-1'
		},
	'meta': 
		{
			'modelName': 'BotVacD7Connected',
			'firmware': '4.5.3-189'
		}
	}


Boundary for plan2
 {
	'version': 1,'reqId': '1','result': 'not_found','data': {},'error': None, 'alert': None, 'state': 1, 
	'action': 0, 'cleaning': 
	{
	'category': 4,'mode': 2, 'modifier': 1,'navigationMode': 1,'mapId': '',	'spotWidth': 0,'spotHeight': 0
	},
'details': 
	{
	'isCharging': False,'isDocked': True,'isScheduleEnabled': False,'dockHasBeenSeen': False,'charge': 95
	}, 
'availableCommands': 
	{
	'start': True,'stop': False,'pause': False,'resume': False,'goToBase': False
	},
'availableServices':
	{
	'findMe': 'basic-1','generalInfo': 'basic-1','houseCleaning': 'basic-4','IECTest': 'advanced-1','logCopy': 'basic-1',
	'manualCleaning': 'basic-1','maps': 'basic-2','preferences': 'basic-2','schedule': 'basic-2','softwareUpdate': 'basic-1',
	'spotCleaning': 'basic-3','wifi': 'basic-1'
	},
'meta':
	{
	'modelName': 'BotVacD7Connected',
	'firmware': '4.5.3-189'
	}
}

So, no zones! It would be nice to get this working. I’m writing a python script in appdaemon that deactivates the motion alarm when it’s time to start the vacuuming, but I’m stuck at this point.
Yet, again, it works if I send the command to clean the zone on the first floor I created in the app, but not on the second floor. Am I missing something, should I query something else? Why can’t I see the zones, and why can I only start a zone cleaning on one floor?

Hey I was helping you out on GitHub. Looking at the code you sent regarding boundary for plan1 that is actually just the state and it is not listing the boundaries.

You actually need to provide the map id instead of the map name when you call for the boundaries. You can find that ID when you call persistent_maps. The format would look like 2019-08-27T18:12:17Z

These are the boundaries that we grab here: https://github.com/home-assistant/home-assistant/blob/2365e2e8cf60f6e86e9033f27082750526825209/homeassistant/components/neato/vacuum.py#L245-L249

You can see here that we are adding them to a list for each map that you have saved. I am not sure why its not working for you but lets take a look at the data provided with the persistent_maps call as well as the correct boundaries. You can remove the URLs I only want to see the map data and boundary data to see what happened.

Thanks! My Neato’s SW got a little messed up one time when it was about to store new maps (I bought an extra docking station for 2nd floor), and now it can’t create new maps or use existing ones. I’m being helped by their support, and as soon as it’s fixed I’ll start testing your suggestions. Thanks again!

Hi,

I’m encoutering the exact same problem. Zone cleaning on the second floor is no problem, but on the first floor it’s saying: “Zone ‘ZONENAME’ was not found for the robot ‘Tippi wan’”.

I’ve read about the problem that it only finds the first map. It seems that i’m having that problem here too. I also read (on github too) that this problem has been solved. Unfortunately not for me (and fabian in this topic too).

I’m running HASSIO 107.7 on a Pi3.

If there is anything i can do, please let me know. It would be great if this problem is solved.

Please follow the steps outlined in this post and show the output of those commands. You need to interact with the parent library so we can see what data is showing up for our zones.

Took some time to figure it out to get the output, but here it is;

{'SERIAL_ID_HERE': [{'id': '2020-04-03T06:34:17Z', 'name': 'Benedenverdieping', 'url': 'URL_HERE', 'raw_floor_map_url': 'RAW_URL_HERE', 'url_valid_for_seconds': 300}, {'id': '2020-03-07T15:27:43Z', 'name': '1e verdieping', 'url': 'URL_HERE', 'raw_floor_map_url': 'RAW_URL_HERE', 'url_valid_for_seconds': 300}]}

Boundary for plan1 {'version': 1, 'reqId': '1', 'result': 'not_found', 'data': {}, 'error': None, 'alert': None, 'state': 1, 'action': 0, 'cleaning': {'category': 4, 'mode': 2, 'modifier': 1, 'navigationMode': 1, 'mapId': '', 'spotWidth': 0, 'spotHeight': 0}, 'details': {'isCharging': False, 'isDocked': True, 'isScheduleEnabled': True, 'dockHasBeenSeen': False, 'charge': 95}, 'availableCommands': {'start': True, 'stop': False, 'pause': False, 'resume': False, 'goToBase': False}, 'availableServices': {'findMe': 'basic-1', 'generalInfo': 'basic-1', 'houseCleaning': 'basic-4', 'IECTest': 'advanced-1', 'logCopy': 'basic-1', 'manualCleaning': 'basic-1', 'maps': 'basic-2', 'preferences': 'basic-2', 'schedule': 'basic-2', 'softwareUpdate': 'basic-1', 'spotCleaning': 'basic-3', 'wifi': 'basic-1'}, 'meta': {'modelName': 'BotVacD7Connected', 'firmware': '4.5.3-189'}}
Boundary for plan2 {'version': 1, 'reqId': '1', 'result': 'not_found', 'data': {}, 'error': None, 'alert': None, 'state': 1, 'action': 0, 'cleaning': {'category': 4, 'mode': 2, 'modifier': 1, 'navigationMode': 1, 'mapId': '', 'spotWidth': 0, 'spotHeight': 0}, 'details': {'isCharging': False, 'isDocked': True, 'isScheduleEnabled': True, 'dockHasBeenSeen': False, 'charge': 95}, 'availableCommands': {'start': True, 'stop': False, 'pause': False, 'resume': False, 'goToBase': False}, 'availableServices': {'findMe': 'basic-1', 'generalInfo': 'basic-1', 'houseCleaning': 'basic-4', 'IECTest': 'advanced-1', 'logCopy': 'basic-1', 'manualCleaning': 'basic-1', 'maps': 'basic-2', 'preferences': 'basic-2', 'schedule': 'basic-2', 'softwareUpdate': 'basic-1', 'spotCleaning': 'basic-3', 'wifi': 'basic-1'}, 'meta': {'modelName': 'BotVacD7Connected', 'firmware': '4.5.3-189'}}

I installed Hassio also in Virtual Box on Ubuntu, (so i could access PIP and install pybotvac etc), and i also got the problem there. On Virtual Box i created the output as above.

So, also on Virtual Box i encounter the ‘zone not found’ problems. However, zones from ‘1e verdieping’ is no problem. Only zones from ‘Benedenverdieping’ cannot be found.

You need to use the map ID instead of the map name. The data you provided is just the state call for the device. I need the actual boundary data. Just replace the name you used with the ID for each map.

  boundary = robot.get_map_boundaries('2020-04-03T06:34:17Z').json()
  print ("Boundary for plan1",boundary)
  boundary = robot.get_map_boundaries('2020-03-07T15:27:43Z').json()
  print ("Boundary for plan2",boundary)

Sounds obvious, excuse, hereby the new data:

Boundary for plan1 {'version': 1, 'reqId': '1', 'result': 'ok', 'data': {'boundaries': [{'id': 'f04a63de-941b-4154-b3ab-5955eb561ad9', 'type': 'polygon', 'vertices': [[0.5161, 0.356], [0.6309, 0.356], [0.6309, 0.4896], [0.5161, 0.4896]], 'name': 'Yinthe', 'color': '#FFC974', 'enabled': True}, {'id': 'f5e22c37-b94b-4c9f-9114-aeeeced808a8', 'type': 'polygon', 'vertices': [[0.6296, 0.2065], [0.7883, 0.2065], [0.7883, 0.4731], [0.6296, 0.4731]], 'name': 'Keuken', 'color': '#E06A83', 'enabled': True}, {'id': '4b0a91c7-a01c-42ce-8eca-024adac2a5ec', 'type': 'polygon', 'vertices': [[0.2656, 0.2747], [0.3887, 0.2747], [0.3887, 0.459], [0.2656, 0.459]], 'name': 'Tapijt', 'color': '#7BB472', 'enabled': True}, {'id': '9ed44d61-c65a-4fa0-96df-d9c8bd05e38b', 'type': 'polygon', 'vertices': [[0.43, 0.5701], [0.6271, 0.5701], [0.6271, 0.6515], [0.43, 0.6515]], 'name': 'Trapkast', 'color': '#5B7BA5', 'enabled': True}, {'id': '5bba9e41-40a1-421d-8a21-1a7630f2f9dd', 'type': 'polygon', 'vertices': [[0.5838, 0.4843], [0.8201, 0.4843], [0.8201, 0.6938], [0.5838, 0.6938]], 'name': 'Entree', 'color': '#E49770', 'enabled': True}, {'id': '8478da68-ce3a-4700-8efd-747f7cf1b661', 'type': 'polygon', 'vertices': [[0.5012, 0.2374], [0.645, 0.2374], [0.645, 0.438], [0.5012, 0.438]], 'name': 'Eethoek', 'color': '#C46262', 'enabled': True}, {'id': 'e12ed8bb-d6da-4be5-9713-d55964879752', 'type': 'polygon', 'vertices': [[0.2107, 0.1649], [0.5836, 0.1649], [0.5836, 0.7097], [0.2107, 0.7097]], 'name': 'Woonkamer', 'color': '#618BAF', 'enabled': True}]}}
Boundary for plan2 {'version': 1, 'reqId': '1', 'result': 'ok', 'data': {'boundaries': [{'id': '4f5e0a80-ed79-4cf8-a5fd-9559a4f158c7', 'type': 'polyline', 'vertices': [[0.3841, 0.3985], [0.3833, 0.4691]], 'name': '', 'color': '#000000', 'enabled': True}, {'id': '87255273-c034-4c54-84d2-62dcdb84f1ae', 'type': 'polyline', 'vertices': [[0.3774, 0.7211], [0.3456, 0.6915]], 'name': '', 'color': '#000000', 'enabled': True}, {'id': 'b40f5d72-fd15-4a85-9f0d-a37ccc062437', 'type': 'polygon', 'vertices': [[0.4737, 0.4965], [0.7392, 0.4965], [0.7392, 0.7722], [0.4737, 0.7722]], 'name': 'Grote slaapkamer', 'color': '#FFC974', 'enabled': True}, {'id': 'a46a9dd5-6fd9-4375-afa0-4dbc043b7070', 'type': 'polygon', 'vertices': [[0.2951, 0.5854], [0.4782, 0.5854], [0.4782, 0.7965], [0.2951, 0.7965]], 'name': 'Badkamer', 'color': '#E06A83', 'enabled': True}, {'id': '1e45c7f6-0793-48d0-abba-ed4ecba9b23c', 'type': 'polygon', 'vertices': [[0.3841, 0.4001], [0.4724, 0.4001], [0.4724, 0.5875], [0.3841, 0.5875]], 'name': 'Overloop', 'color': '#7BB472', 'enabled': True}, {'id': '60c27ab0-2523-4076-90ce-fccb1691b324', 'type': 'polygon', 'vertices': [[0.5149, 0.2143], [0.7405, 0.2143], [0.7405, 0.4996], [0.5149, 0.4996]], 'name': "Yinthe's slaapkamer", 'color': '#5B7BA5', 'enabled': True}, {'id': 'c892c83d-e878-4876-ab7d-d095f2e632a6', 'type': 'polygon', 'vertices': [[0.2906, 0.217], [0.5168, 0.217], [0.5168, 0.3986], [0.2906, 0.3986]], 'name': 'Computerkamer', 'color': '#E49770', 'enabled': True}]}}
1 Like

Thank you looking at the data now. In your second map are you using zones along with no go lines? I see a polyline listed in the second zone. Can you try removing those and only using zones instead? they dont really act like a zone and I am wondering if the blank name on them is causing an issue.

[{'id': '4f5e0a80-ed79-4cf8-a5fd-9559a4f158c7', 'type': 'polyline', 'vertices': [[0.3841, 0.3985], [0.3833, 0.4691]], 'name': '', 'color': '#000000', 'enabled': True}, 
{'id': '87255273-c034-4c54-84d2-62dcdb84f1ae', 'type': 'polyline', 'vertices': [[0.3774, 0.7211], [0.3456, 0.6915]], 'name': '', 'color': '#000000', 'enabled': True},

These are different than the typical zones:

{'id': 'b40f5d72-fd15-4a85-9f0d-a37ccc062437', 'type': 'polygon', 'vertices': [[0.4737, 0.4965], [0.7392, 0.4965], [0.7392, 0.7722], [0.4737, 0.7722]], 'name': 'Grote slaapkamer', 'color': '#FFC974', 'enabled': True}, 

I removed the two noGo lines from plan 2.

Newly output:

Boundary for plan1 {'version': 1, 'reqId': '1', 'result': 'ok', 'data': {'boundaries': [{'id': 'f04a63de-941b-4154-b3ab-5955eb561ad9', 'type': 'polygon', 'vertices': [[0.5161, 0.356], [0.6309, 0.356], [0.6309, 0.4896], [0.5161, 0.4896]], 'name': 'Yinthe', 'color': '#FFC974', 'enabled': True}, {'id': 'f5e22c37-b94b-4c9f-9114-aeeeced808a8', 'type': 'polygon', 'vertices': [[0.6296, 0.2065], [0.7883, 0.2065], [0.7883, 0.4731], [0.6296, 0.4731]], 'name': 'Keuken', 'color': '#E06A83', 'enabled': True}, {'id': '4b0a91c7-a01c-42ce-8eca-024adac2a5ec', 'type': 'polygon', 'vertices': [[0.2656, 0.2747], [0.3887, 0.2747], [0.3887, 0.459], [0.2656, 0.459]], 'name': 'Tapijt', 'color': '#7BB472', 'enabled': True}, {'id': '9ed44d61-c65a-4fa0-96df-d9c8bd05e38b', 'type': 'polygon', 'vertices': [[0.43, 0.5701], [0.6271, 0.5701], [0.6271, 0.6515], [0.43, 0.6515]], 'name': 'Trapkast', 'color': '#5B7BA5', 'enabled': True}, {'id': '5bba9e41-40a1-421d-8a21-1a7630f2f9dd', 'type': 'polygon', 'vertices': [[0.5838, 0.4843], [0.8201, 0.4843], [0.8201, 0.6938], [0.5838, 0.6938]], 'name': 'Entree', 'color': '#E49770', 'enabled': True}, {'id': '8478da68-ce3a-4700-8efd-747f7cf1b661', 'type': 'polygon', 'vertices': [[0.5012, 0.2374], [0.645, 0.2374], [0.645, 0.438], [0.5012, 0.438]], 'name': 'Eethoek', 'color': '#C46262', 'enabled': True}, {'id': 'e12ed8bb-d6da-4be5-9713-d55964879752', 'type': 'polygon', 'vertices': [[0.2107, 0.1649], [0.5836, 0.1649], [0.5836, 0.7097], [0.2107, 0.7097]], 'name': 'Woonkamer', 'color': '#618BAF', 'enabled': True}]}}
Boundary for plan2 {'version': 1, 'reqId': '1', 'result': 'ok', 'data': {'boundaries': [{'id': 'b40f5d72-fd15-4a85-9f0d-a37ccc062437', 'type': 'polygon', 'vertices': [[0.4737, 0.4965], [0.7392, 0.4965], [0.7392, 0.7722], [0.4737, 0.7722]], 'name': 'Grote slaapkamer', 'color': '#FFC974', 'enabled': True}, {'id': 'a46a9dd5-6fd9-4375-afa0-4dbc043b7070', 'type': 'polygon', 'vertices': [[0.2951, 0.5854], [0.4782, 0.5854], [0.4782, 0.7965], [0.2951, 0.7965]], 'name': 'Badkamer', 'color': '#E06A83', 'enabled': True}, {'id': '1e45c7f6-0793-48d0-abba-ed4ecba9b23c', 'type': 'polygon', 'vertices': [[0.3841, 0.4001], [0.4724, 0.4001], [0.4724, 0.5875], [0.3841, 0.5875]], 'name': 'Overloop', 'color': '#7BB472', 'enabled': True}, {'id': '60c27ab0-2523-4076-90ce-fccb1691b324', 'type': 'polygon', 'vertices': [[0.5149, 0.2143], [0.7405, 0.2143], [0.7405, 0.4996], [0.5149, 0.4996]], 'name': "Yinthe's slaapkamer", 'color': '#5B7BA5', 'enabled': True}, {'id': 'c892c83d-e878-4876-ab7d-d095f2e632a6', 'type': 'polygon', 'vertices': [[0.2906, 0.217], [0.5168, 0.217], [0.5168, 0.3986], [0.2906, 0.3986]], 'name': 'Computerkamer', 'color': '#E49770', 'enabled': True}]}}

However, plan2 isn’t the problem. I tried calling service custom_cleaning with zone; ‘Overloop’ and the robot was activating (even with noGo lines like i tried earlier), but, it’s saying; i’m on the wrong floor (that’s correct).

Plan 1, however, does not work with custom_cleaning. E.g. zone ‘Eethoek’ or ‘Woonkamer’ does not do anything and fires these log entries in Hassio:

Logger: homeassistant.components.neato.vacuum
Source: components/neato/vacuum.py:111
Integration: neato (documentation, issues)
First occurred: 20:08:39 (6 occurrences)
Last logged: 20:12:02

Zone 'Eethoek' was not found for the robot 'Tippi wan'
Zone 'Tapijt' was not found for the robot 'Tippi wan'
Zone 'Woonkamer' was not found for the robot 'Tippi wan'
Zone 'Keuken' was not found for the robot 'Tippi wan'

Thanks in advance!

Interesting so the second map is working properly but the first map is not? That is different than what everyone is reporting as everyone else is saying the first map is what works and second map is not.

Are you able to test a custom component with a potential fix?

Let me know your results :slight_smile:

Hello!

Unfortunately it seems there is an error in the code, debug info:

Logger: homeassistant.components.websocket_api.http.connection.1898198128
Source: custom_components/neato/vacuum.py:385
Integration: websocket_api (documentation, issues)
First occurred: 10:46:26 (2 occurrences)
Last logged: 10:48:41

'int' object is not subscriptable
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/websocket_api/commands.py", line 134, in handle_call_service
    connection.context(msg),
  File "/usr/src/homeassistant/homeassistant/core.py", line 1234, in async_call
    await asyncio.shield(self._execute_service(handler, service_call))
  File "/usr/src/homeassistant/homeassistant/core.py", line 1261, in _execute_service
    await self._hass.async_add_executor_job(handler.func, service_call)
  File "/usr/local/lib/python3.7/concurrent/futures/thread.py", line 57, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/config/custom_components/neato/vacuum.py", line 111, in neato_custom_cleaning_service
    robot.neato_custom_cleaning(mode, navigation, category, zone)
  File "/config/custom_components/neato/vacuum.py", line 385, in neato_custom_cleaning
    if zone in boundary["name"]:
TypeError: 'int' object is not subscriptable

if you need more info, please let me know. And of course, thanks again in advance!

Thank you for testing! Can you update this file and try again please?

Your welcome!

Unfortunately i’m encoutering the exact same error:

Logger: homeassistant.components.websocket_api.http.connection.1815898960
Source: custom_components/neato/vacuum.py:385
Integration: websocket_api (documentation, issues)
First occurred: 11:00:41 (1 occurrences)
Last logged: 11:00:41

'int' object is not subscriptable
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/websocket_api/commands.py", line 134, in handle_call_service
    connection.context(msg),
  File "/usr/src/homeassistant/homeassistant/core.py", line 1234, in async_call
    await asyncio.shield(self._execute_service(handler, service_call))
  File "/usr/src/homeassistant/homeassistant/core.py", line 1261, in _execute_service
    await self._hass.async_add_executor_job(handler.func, service_call)
  File "/usr/local/lib/python3.7/concurrent/futures/thread.py", line 57, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/config/custom_components/neato/vacuum.py", line 111, in neato_custom_cleaning_service
    robot.neato_custom_cleaning(mode, navigation, category, zone)
  File "/config/custom_components/neato/vacuum.py", line 385, in neato_custom_cleaning
    for boundary in boundaries["data"]["boundaries"]:
TypeError: 'int' object is not subscriptable

If there is anything i can do, just let me know :slight_smile:

Hi dshokouhi, any updates on this? i tried to debug it, but couldn’t fix it, hope you can. If you need anything, just let me know! :slight_smile:

I haven’t had much luck honestly, but I still haven’t been able to reproduce it either. Looking at the original code again and a previous users confirmation I think there may be something else I am not seeing. The code was designed to grab all the maps and boundaries which is why some work but not sure why the others don’t.

If i’m reading the error; ‘int’ object is not subscriptable, sounds to me like an error before the code reaches the boundaries?

Is it possible to debug the code by putting some var_dumps on some places? If you put them in code, i can test it again. And ofcourse, i’m willing to help to solve this. Maybe by teamviewer or something?

That code that I gave you is not going to work, we’ll need to look at what was published and see whats going on there. I am stuck on why its not working because its working for me, if you are able to debug it that would be helpful. The old code was designed to look at only the first floorplan and now we look at all. We may need someone else to come in and help debug.

I actually solved it here, but on the dirty way:

self._robot_boundaries_floor1 = {}
self._robot_boundaries_floor2 = {}
self._robot_boundaries_floor3 = {}

---

self._robot_boundaries_floor1 = self.robot.get_map_boundaries('2020-04-03T06:34:17Z').json()
self._robot_boundaries_floor2 = self.robot.get_map_boundaries('2020-03-07T15:27:43Z').json()
#floor3 is not measured yet.

---

for boundary in self._robot_boundaries_floor1["data"]["boundaries"]:
	if zone in boundary["name"]:
		boundary_id = boundary["id"]
		
for boundary in self._robot_boundaries_floor2["data"]["boundaries"]:
	if zone in boundary["name"]:
		boundary_id = boundary["id"]

# floor 3 is not measured yet

Everything worked, but i couldn’t fix the " ‘int’ object is not subscriptable " bug. Seems like it has something to do with the dictionary [x] and calling objects from it.

But with my ‘solution’, i’ll get this error the first time i’ll call the service after restarting HA:

string value is None for dictionary value @ data['zone']

But i’ll take a look on it today.