2016-11-19 08:14:40 +00:00
|
|
|
"""
|
|
|
|
Support for Neato Connected Vaccums sensors.
|
|
|
|
|
|
|
|
For more details about this platform, please refer to the documentation at
|
|
|
|
https://home-assistant.io/components/sensor.neato/
|
|
|
|
"""
|
|
|
|
import logging
|
2017-04-03 12:42:21 +00:00
|
|
|
import requests
|
2016-11-19 08:14:40 +00:00
|
|
|
from homeassistant.helpers.entity import Entity
|
2016-11-22 03:36:44 +00:00
|
|
|
from homeassistant.components.neato import (
|
2017-04-13 14:41:25 +00:00
|
|
|
NEATO_ROBOTS, NEATO_LOGIN, NEATO_MAP_DATA, ACTION, ERRORS, MODE, ALERTS)
|
2016-11-19 08:14:40 +00:00
|
|
|
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
2017-04-13 14:41:25 +00:00
|
|
|
|
|
|
|
DEPENDENCIES = ['neato']
|
|
|
|
|
2016-11-19 08:14:40 +00:00
|
|
|
SENSOR_TYPE_STATUS = 'status'
|
|
|
|
SENSOR_TYPE_BATTERY = 'battery'
|
|
|
|
|
|
|
|
SENSOR_TYPES = {
|
|
|
|
SENSOR_TYPE_STATUS: ['Status'],
|
|
|
|
SENSOR_TYPE_BATTERY: ['Battery']
|
|
|
|
}
|
|
|
|
|
2017-04-13 14:41:25 +00:00
|
|
|
ATTR_CLEAN_START = 'clean_start'
|
|
|
|
ATTR_CLEAN_STOP = 'clean_stop'
|
|
|
|
ATTR_CLEAN_AREA = 'clean_area'
|
|
|
|
ATTR_CLEAN_BATTERY_START = 'battery_level_at_clean_start'
|
|
|
|
ATTR_CLEAN_BATTERY_END = 'battery_level_at_clean_end'
|
|
|
|
ATTR_CLEAN_SUSP_COUNT = 'clean_suspension_count'
|
|
|
|
ATTR_CLEAN_SUSP_TIME = 'clean_suspension_time'
|
|
|
|
|
2016-11-19 08:14:40 +00:00
|
|
|
|
|
|
|
def setup_platform(hass, config, add_devices, discovery_info=None):
|
2017-05-02 16:18:47 +00:00
|
|
|
"""Set up the Neato sensor platform."""
|
2016-11-19 08:14:40 +00:00
|
|
|
dev = []
|
|
|
|
for robot in hass.data[NEATO_ROBOTS]:
|
|
|
|
for type_name in SENSOR_TYPES:
|
|
|
|
dev.append(NeatoConnectedSensor(hass, robot, type_name))
|
2017-05-02 16:18:47 +00:00
|
|
|
_LOGGER.debug("Adding sensors %s", dev)
|
2016-11-19 08:14:40 +00:00
|
|
|
add_devices(dev)
|
|
|
|
|
|
|
|
|
|
|
|
class NeatoConnectedSensor(Entity):
|
|
|
|
"""Neato Connected Sensor."""
|
|
|
|
|
|
|
|
def __init__(self, hass, robot, sensor_type):
|
|
|
|
"""Initialize the Neato Connected sensor."""
|
|
|
|
self.type = sensor_type
|
|
|
|
self.robot = robot
|
|
|
|
self.neato = hass.data[NEATO_LOGIN]
|
|
|
|
self._robot_name = self.robot.name + ' ' + SENSOR_TYPES[self.type][0]
|
|
|
|
self._status_state = None
|
2017-04-13 14:41:25 +00:00
|
|
|
try:
|
|
|
|
self._state = self.robot.state
|
|
|
|
except (requests.exceptions.ConnectionError,
|
|
|
|
requests.exceptions.HTTPError) as ex:
|
|
|
|
self._state = None
|
2017-05-02 16:18:47 +00:00
|
|
|
_LOGGER.warning("Neato connection error: %s", ex)
|
2017-04-13 14:41:25 +00:00
|
|
|
self._mapdata = hass.data[NEATO_MAP_DATA]
|
|
|
|
self.clean_time_start = None
|
|
|
|
self.clean_time_stop = None
|
|
|
|
self.clean_area = None
|
|
|
|
self.clean_battery_start = None
|
|
|
|
self.clean_battery_end = None
|
|
|
|
self.clean_suspension_charge_count = None
|
|
|
|
self.clean_suspension_time = None
|
|
|
|
self._battery_state = None
|
2016-11-19 08:14:40 +00:00
|
|
|
|
|
|
|
def update(self):
|
|
|
|
"""Update the properties of sensor."""
|
|
|
|
_LOGGER.debug('Update of sensor')
|
|
|
|
self.neato.update_robots()
|
2017-04-13 14:41:25 +00:00
|
|
|
self._mapdata = self.hass.data[NEATO_MAP_DATA]
|
2017-04-03 12:42:21 +00:00
|
|
|
try:
|
|
|
|
self._state = self.robot.state
|
2017-04-13 14:41:25 +00:00
|
|
|
except (requests.exceptions.ConnectionError,
|
|
|
|
requests.exceptions.HTTPError) as ex:
|
2017-04-03 12:42:21 +00:00
|
|
|
self._state = None
|
|
|
|
self._status_state = 'Offline'
|
2017-05-02 16:18:47 +00:00
|
|
|
_LOGGER.warning("Neato connection error: %s", ex)
|
2017-04-13 14:41:25 +00:00
|
|
|
return
|
|
|
|
if not self._state:
|
2017-04-03 12:42:21 +00:00
|
|
|
return
|
2016-11-19 08:14:40 +00:00
|
|
|
_LOGGER.debug('self._state=%s', self._state)
|
|
|
|
if self.type == SENSOR_TYPE_STATUS:
|
|
|
|
if self._state['state'] == 1:
|
|
|
|
if self._state['details']['isCharging']:
|
|
|
|
self._status_state = 'Charging'
|
|
|
|
elif (self._state['details']['isDocked'] and
|
|
|
|
not self._state['details']['isCharging']):
|
|
|
|
self._status_state = 'Docked'
|
|
|
|
else:
|
|
|
|
self._status_state = 'Stopped'
|
|
|
|
elif self._state['state'] == 2:
|
|
|
|
if ALERTS.get(self._state['error']) is None:
|
2016-11-19 08:46:02 +00:00
|
|
|
self._status_state = (
|
|
|
|
MODE.get(self._state['cleaning']['mode'])
|
|
|
|
+ ' ' + ACTION.get(self._state['action']))
|
2016-11-19 08:14:40 +00:00
|
|
|
else:
|
|
|
|
self._status_state = ALERTS.get(self._state['error'])
|
|
|
|
elif self._state['state'] == 3:
|
|
|
|
self._status_state = 'Paused'
|
|
|
|
elif self._state['state'] == 4:
|
|
|
|
self._status_state = ERRORS.get(self._state['error'])
|
|
|
|
if self.type == SENSOR_TYPE_BATTERY:
|
|
|
|
self._battery_state = self._state['details']['charge']
|
2017-08-09 21:22:08 +00:00
|
|
|
if not self._mapdata.get(self.robot.serial, {}).get('maps', []):
|
2017-04-13 14:41:25 +00:00
|
|
|
return
|
|
|
|
self.clean_time_start = (
|
|
|
|
(self._mapdata[self.robot.serial]['maps'][0]['start_at']
|
|
|
|
.strip('Z'))
|
|
|
|
.replace('T', ' '))
|
|
|
|
self.clean_time_stop = (
|
|
|
|
(self._mapdata[self.robot.serial]['maps'][0]['end_at'].strip('Z'))
|
|
|
|
.replace('T', ' '))
|
|
|
|
self.clean_area = (
|
|
|
|
self._mapdata[self.robot.serial]['maps'][0]['cleaned_area'])
|
|
|
|
self.clean_suspension_charge_count = (
|
|
|
|
self._mapdata[self.robot.serial]['maps'][0]
|
|
|
|
['suspended_cleaning_charging_count'])
|
|
|
|
self.clean_suspension_time = (
|
|
|
|
self._mapdata[self.robot.serial]['maps'][0]
|
|
|
|
['time_in_suspended_cleaning'])
|
|
|
|
self.clean_battery_start = (
|
|
|
|
self._mapdata[self.robot.serial]['maps'][0]['run_charge_at_start'])
|
|
|
|
self.clean_battery_end = (
|
|
|
|
self._mapdata[self.robot.serial]['maps'][0]['run_charge_at_end'])
|
2016-11-19 08:14:40 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
def unit_of_measurement(self):
|
|
|
|
"""Return unit for the sensor."""
|
|
|
|
if self.type == SENSOR_TYPE_BATTERY:
|
|
|
|
return '%'
|
|
|
|
|
|
|
|
@property
|
|
|
|
def available(self):
|
|
|
|
"""Return True if sensor data is available."""
|
2017-07-06 06:30:01 +00:00
|
|
|
return self._state
|
2016-11-19 08:14:40 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
def state(self):
|
|
|
|
"""Return the sensor state."""
|
|
|
|
if self.type == SENSOR_TYPE_STATUS:
|
|
|
|
return self._status_state
|
|
|
|
if self.type == SENSOR_TYPE_BATTERY:
|
|
|
|
return self._battery_state
|
|
|
|
|
|
|
|
@property
|
|
|
|
def name(self):
|
|
|
|
"""Return the name of the sensor."""
|
|
|
|
return self._robot_name
|
2017-04-13 14:41:25 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
def device_state_attributes(self):
|
|
|
|
"""Return the device specific attributes."""
|
|
|
|
data = {}
|
|
|
|
if self.type is SENSOR_TYPE_STATUS:
|
|
|
|
if self.clean_time_start:
|
|
|
|
data[ATTR_CLEAN_START] = self.clean_time_start
|
|
|
|
if self.clean_time_stop:
|
|
|
|
data[ATTR_CLEAN_STOP] = self.clean_time_stop
|
|
|
|
if self.clean_area:
|
|
|
|
data[ATTR_CLEAN_AREA] = self.clean_area
|
|
|
|
if self.clean_suspension_charge_count:
|
|
|
|
data[ATTR_CLEAN_SUSP_COUNT] = (
|
|
|
|
self.clean_suspension_charge_count)
|
|
|
|
if self.clean_suspension_time:
|
|
|
|
data[ATTR_CLEAN_SUSP_TIME] = self.clean_suspension_time
|
|
|
|
if self.clean_battery_start:
|
|
|
|
data[ATTR_CLEAN_BATTERY_START] = self.clean_battery_start
|
|
|
|
if self.clean_battery_end:
|
|
|
|
data[ATTR_CLEAN_BATTERY_END] = self.clean_battery_end
|
|
|
|
return data
|