Compare commits

...

10 Commits
v0.9.4 ... main

Author SHA1 Message Date
314a9ef4a5 „repository.json“ hinzufügen 2022-11-25 19:40:20 +00:00
7274cd623f Merge pull request 'Enable map support' (#1) from yeet into main
Reviewed-on: #1
2022-11-22 10:26:43 +00:00
Fuempel
73589d9268
Fix translation issue during integration setup
Not working link causes strange dialog display during integration configuration phase.
2022-06-19 17:06:54 +02:00
Fuempel
9c021a5226
Review findings correction for zone cleaning support 2022-06-19 16:41:38 +02:00
Fuempel
024e5e5fae
Implement zone support for VR 300 2022-06-19 16:14:42 +02:00
Michael Graf
e19ab3e1bd Fix mypy error 2021-12-28 17:00:47 +01:00
Michael Graf
418469cda7 Bump Version 0.9.6 2021-12-28 16:44:15 +01:00
Michael Graf
2d1c6ecad8 Fix vacuum won't start when docked #4 2021-12-28 16:43:33 +01:00
Michael Graf
ca06f15029 Update manifest to 0.9.5 2021-12-28 12:42:18 +01:00
Michael Graf
d00e44ca5d Fix vacuum won't start when docked #4 2021-12-28 12:39:31 +01:00
8 changed files with 87 additions and 24 deletions

View File

@ -8,6 +8,7 @@ from typing import Any
from pybotvac.exceptions import NeatoException, NeatoRobotException
from pybotvac.robot import Robot
from pybotvac.vorwerk import Vorwerk
from pybotvac.session import PasswordlessSession
import voluptuous as vol
from homeassistant.components.vacuum import (
@ -24,6 +25,7 @@ import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.typing import ConfigType, HomeAssistantType
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
from homeassistant.const import CONF_TOKEN
from .const import (
ACTION,
@ -97,6 +99,7 @@ async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry) -> bool
{
VORWERK_ROBOT_API: r,
VORWERK_ROBOT_COORDINATOR: _create_coordinator(hass, r),
CONF_TOKEN: entry.data[CONF_TOKEN]
}
for r in robot_states
]

View File

@ -23,6 +23,7 @@ MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=1)
ATTR_NAVIGATION = "navigation"
ATTR_CATEGORY = "category"
ATTR_ZONE = "zone"
ATTR_MAP = "map"
ROBOT_STATE_INVALID = 0
ROBOT_STATE_IDLE = 1

View File

@ -2,16 +2,17 @@
"domain": "vorwerk",
"name": "Vorwerk Kobold",
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/vorwerk",
"documentation": "https://github.com/trunneml/homeassistant-vorwerk",
"requirements": [
"pybotvac==0.0.20"
"pybotvac==0.0.23"
],
"codeowners": [
"@trunneml"
"@trunneml",
"@fuempel"
],
"dependencies": [
"http"
],
"iot_class": "cloud_polling",
"version": "0.9.4"
"version": "0.10.0"
}

5
repository.json Normal file
View File

@ -0,0 +1,5 @@
{
"name": "Eriks homeassistant-vorwerk addon",
"url": "https://git.sfs.ddnss.org/SFS/homeassistant-vorwerk",
"maintainer": "Erik Foris <erikfor@outlook.de"
}

View File

@ -16,3 +16,6 @@ custom_cleaning:
zone:
description: Only supported on the VR300. Name of the zone to clean. Defaults to no zone i.e. complete house cleanup.
example: "Kitchen"
map:
description: Only supported on the VR300. Name of the map for the zone to clean. Defaults to no zone i.e. complete house cleanup.
example: "Ground Floor"

View File

@ -6,14 +6,14 @@
"data": {
"email": "E-Mailaddresse"
},
"description": "Um einen Authentifizierungscode per E-Mail zu erhalten, gib die E-Mailadresse deines Vorwerk-Accounts ein.\n\nSiehe [Vorwerk-Dokumentation]({docs_url})."
"description": "Um einen Authentifizierungscode per E-Mail zu erhalten, gib die E-Mailadresse deines Vorwerk-Accounts ein."
},
"code": {
"title": "Vorwerk Account Info",
"data": {
"code": "Code"
},
"description": "Gib den per E-Mail erhaltenen Code ein.\n\nSee [Vorwerk documentation]({docs_url})."
"description": "Gib den per E-Mail erhaltenen Code ein."
}
},
"error": {

View File

@ -6,14 +6,14 @@
"data": {
"email": "Email"
},
"description": "To recieve an authentication code, enter the email address of your vorwerk account.\n\nSee [Vorwerk documentation]({docs_url})."
"description": "To recieve an authentication code, enter the email address of your vorwerk account."
},
"code": {
"title": "Vorwerk Account Info",
"data": {
"code": "Code"
},
"description": "Enter the code you received by email.\n\nSee [Vorwerk documentation]({docs_url})."
"description": "Enter the code you received by email."
}
},
"error": {

View File

@ -5,12 +5,15 @@ import logging
from typing import Any
from pybotvac import Robot
from pybotvac.session import PasswordlessSession
from pybotvac.account import Account
from pybotvac.exceptions import NeatoRobotException
import voluptuous as vol
from homeassistant.components.vacuum import (
ATTR_STATUS,
STATE_CLEANING,
STATE_DOCKED,
STATE_IDLE,
STATE_PAUSED,
SUPPORT_BATTERY,
@ -23,7 +26,7 @@ from homeassistant.components.vacuum import (
SUPPORT_STOP,
StateVacuumEntity,
)
from homeassistant.const import ATTR_MODE
from homeassistant.const import ATTR_MODE, CONF_TOKEN
from homeassistant.helpers import config_validation as cv, entity_platform
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.update_coordinator import (
@ -35,10 +38,12 @@ from .const import (
ATTR_CATEGORY,
ATTR_NAVIGATION,
ATTR_ZONE,
ATTR_MAP,
VORWERK_DOMAIN,
VORWERK_ROBOT_API,
VORWERK_ROBOT_COORDINATOR,
VORWERK_ROBOTS,
VORWERK_CLIENT_ID,
)
_LOGGER = logging.getLogger(__name__)
@ -63,7 +68,7 @@ async def async_setup_entry(hass, entry, async_add_entities):
async_add_entities(
[
VorwerkConnectedVacuum(
robot[VORWERK_ROBOT_API], robot[VORWERK_ROBOT_COORDINATOR]
robot[VORWERK_ROBOT_API], robot[VORWERK_ROBOT_COORDINATOR], robot[CONF_TOKEN]
)
for robot in hass.data[VORWERK_DOMAIN][entry.entry_id][VORWERK_ROBOTS]
],
@ -80,6 +85,7 @@ async def async_setup_entry(hass, entry, async_add_entities):
vol.Optional(ATTR_NAVIGATION, default=1): cv.positive_int,
vol.Optional(ATTR_CATEGORY, default=4): cv.positive_int,
vol.Optional(ATTR_ZONE): cv.string,
vol.Optional(ATTR_MAP): cv.string,
},
"vorwerk_custom_cleaning",
)
@ -89,7 +95,7 @@ class VorwerkConnectedVacuum(CoordinatorEntity, StateVacuumEntity):
"""Representation of a Vorwerk Connected Vacuum."""
def __init__(
self, robot_state: VorwerkState, coordinator: DataUpdateCoordinator[Any]
self, robot_state: VorwerkState, coordinator: DataUpdateCoordinator[Any], token
) -> None:
"""Initialize the Vorwerk Connected Vacuum."""
super().__init__(coordinator)
@ -98,7 +104,7 @@ class VorwerkConnectedVacuum(CoordinatorEntity, StateVacuumEntity):
self._name = f"{self.robot.name}"
self._robot_serial = self.robot.serial
self._robot_boundaries: list[str] = []
self._token = token
@property
def name(self) -> str:
@ -155,7 +161,7 @@ class VorwerkConnectedVacuum(CoordinatorEntity, StateVacuumEntity):
if not self._state:
return
try:
if self._state.state == STATE_IDLE:
if self._state.state == STATE_IDLE or self._state.state == STATE_DOCKED:
self.robot.start_cleaning()
elif self._state.state == STATE_PAUSED:
self.robot.resume_cleaning()
@ -212,23 +218,67 @@ class VorwerkConnectedVacuum(CoordinatorEntity, StateVacuumEntity):
)
def vorwerk_custom_cleaning(
self, mode: str, navigation: str, category: str, zone: str | None = None
self, mode: str, navigation: str, category: str, zone: str, map: str | None = None
) -> None:
"""Zone cleaning service call."""
_LOGGER.debug("vorwerk_custom_cleaning called for %s / %s with token %s", map, zone, self._token)
# create Vorwerk API session + account object and populate the robot list
# (this necessary to update pybotvac internal states)
session = PasswordlessSession(client_id=VORWERK_CLIENT_ID, token=self._token)
account = Account(session)
robots = account.robots
_LOGGER.debug(" Robot list = %s", robots)
map_id = None
boundary_id = None
if zone is not None:
for boundary in self._robot_boundaries:
if zone in boundary["name"]:
boundary_id = boundary["id"]
if boundary_id is None:
_LOGGER.error(
"Zone '%s' was not found for the robot '%s'", zone, self.entity_id
)
if map is not None:
# search map
maps = account.persistent_maps[self._robot_serial]
_LOGGER.debug(" Persistent map list = %s", maps)
map_obj = None
available_maps = []
for m in maps:
available_maps.append(m['name'])
if map in m['name']:
map_obj = m
if map_obj is None:
_LOGGER.error("Map '%s' was not found for the robot '%s', list of valid maps: %s", map, self.entity_id, available_maps)
return
_LOGGER.info("Start cleaning zone '%s' with robot %s", zone, self.entity_id)
map_id = map_obj['id']
_LOGGER.debug(" Found map %s = ID %s", map, map_id)
if zone is not None:
# search zone = boundary ID
boundaries = self.robot.get_map_boundaries(map_id).json()
_LOGGER.debug(" Boundary list = %s", boundaries)
boundary_obj = None
available_zones = []
for b in boundaries['data']['boundaries']:
available_zones.append(b['name'])
if zone in b['name']:
boundary_obj = b
if boundary_obj is None:
_LOGGER.error("Zone '%s' was not found for the robot '%s' on map '%s', list of valid zones: %s", zone, self.entity_id, map, available_zones)
return
boundary_id = boundary_obj['id']
_LOGGER.debug(" Found baundary / zone %s = ID %s", zone, boundary_id)
# start cleaning now
_LOGGER.info("Start cleaning zone '%s' on map '%s' with robot %s", zone, map, self.entity_id)
try:
self.robot.start_cleaning(mode, navigation, category, boundary_id)
self.robot.start_cleaning(mode, navigation, category, boundary_id, map_id)
except NeatoRobotException as ex:
_LOGGER.error(
"Vorwerk vacuum connection error for '%s': %s", self.entity_id, ex