Upgrade to 0.73 for #395

This commit is contained in:
ccostan 2018-07-07 10:23:46 -04:00
parent 0d889da2b6
commit e54e19c341
11 changed files with 86 additions and 601 deletions

View File

@ -1 +1 @@
0.72.1
0.73.0

View File

@ -1,48 +0,0 @@
[
{
"data": {
"bridge_id": "001788FFFE2B695A",
"host": "192.168.10.75",
"username": "UplIVZey-wUXCfTG7Jf99pfEMjXegMm2H8ciXBvq"
},
"domain": "hue",
"entry_id": "7e9bfa52b2d04ebe82893e4043bf944b",
"source": "import",
"title": "Carlo-Hue2",
"version": 1
},
{
"data": {
"bridge_id": "001788FFFE148545",
"host": "192.168.10.76",
"username": "f2V4X70LAr2Y5yW9LMPziAOuT3XTdbZd-N-J2eaK"
},
"domain": "hue",
"entry_id": "97428cbb507e4afcbe38eb8b9c4f2732",
"source": "import",
"title": "Carlo-Hue1",
"version": 1
},
{
"data": {
"impl_domain": "nest",
"tokens": {
"access_token": "c.qZwzHcUwWHfK927A4CvobNIq3exgmG2kMAV2LcFYVaFd74xfWJXHfQJCGDkqJrybO9UFf6n6bs13cPDgWersBwhA0e3JZMYHZBBxMIOY7KegK78dYoVs4pnaMVQ6k3WUWoJHE8G3TixOnx5F",
"expires_in": 315360000
}
},
"domain": "nest",
"entry_id": "dff91f79d9df415d8788eaf512325435",
"source": "import",
"title": "Nest (import from configuration.yaml)",
"version": 1
},
{
"data": {},
"domain": "cast",
"entry_id": "41c7cbc168f542e88ec8e6a3e37e20fc",
"source": "user",
"title": "Google Cast",
"version": 1
}
]

View File

@ -0,0 +1,54 @@
{
"data": {
"entries": [
{
"data": {
"bridge_id": "001788FFFE2B695A",
"host": "192.168.10.75",
"username": "UplIVZey-wUXCfTG7Jf99pfEMjXegMm2H8ciXBvq"
},
"domain": "hue",
"entry_id": "7e9bfa52b2d04ebe82893e4043bf944b",
"source": "import",
"title": "Carlo-Hue2",
"version": 1
},
{
"data": {
"bridge_id": "001788FFFE148545",
"host": "192.168.10.76",
"username": "f2V4X70LAr2Y5yW9LMPziAOuT3XTdbZd-N-J2eaK"
},
"domain": "hue",
"entry_id": "97428cbb507e4afcbe38eb8b9c4f2732",
"source": "import",
"title": "Carlo-Hue1",
"version": 1
},
{
"data": {
"impl_domain": "nest",
"tokens": {
"access_token": "c.qZwzHcUwWHfK927A4CvobNIq3exgmG2kMAV2LcFYVaFd74xfWJXHfQJCGDkqJrybO9UFf6n6bs13cPDgWersBwhA0e3JZMYHZBBxMIOY7KegK78dYoVs4pnaMVQ6k3WUWoJHE8G3TixOnx5F",
"expires_in": 315360000
}
},
"domain": "nest",
"entry_id": "dff91f79d9df415d8788eaf512325435",
"source": "import",
"title": "Nest (import from configuration.yaml)",
"version": 1
},
{
"data": {},
"domain": "cast",
"entry_id": "41c7cbc168f542e88ec8e6a3e37e20fc",
"source": "user",
"title": "Google Cast",
"version": 1
}
]
},
"key": "core.config_entries",
"version": 1
}

View File

@ -1,65 +0,0 @@
"""
Camera that loads a picture from Neato.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/camera.neato/
"""
import logging
from datetime import timedelta
from homeassistant.components.camera import Camera
from homeassistant.components.neato import (
NEATO_MAP_DATA, NEATO_ROBOTS, NEATO_LOGIN)
from homeassistant.util import Throttle
_LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['neato']
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up the Neato Camera."""
dev = []
for robot in hass.data[NEATO_ROBOTS]:
if 'maps' in robot.traits:
dev.append(NeatoCleaningMap(hass, robot))
_LOGGER.debug("Adding robots for cleaning maps %s", dev)
add_devices(dev, True)
class NeatoCleaningMap(Camera):
"""Neato cleaning map for last clean."""
def __init__(self, hass, robot):
"""Initialize Neato cleaning map."""
super().__init__()
self.robot = robot
self._robot_name = '{} {}'.format(self.robot.name, 'Cleaning Map')
self._robot_serial = self.robot.serial
self.neato = hass.data[NEATO_LOGIN]
self._image_url = None
self._image = None
def camera_image(self):
"""Return image response."""
self.update()
return self._image
@Throttle(timedelta(seconds=60))
def update(self):
"""Check the contents of the map list."""
self.neato.update_robots()
image_url = None
map_data = self.hass.data[NEATO_MAP_DATA]
image_url = map_data[self._robot_serial]['maps'][0]['url']
if image_url == self._image_url:
_LOGGER.debug("The map image_url is the same as old")
return
image = self.neato.download_map(image_url)
self._image = image.read()
self._image_url = image_url
@property
def name(self):
"""Return the name of this camera."""
return self._robot_name

View File

@ -1,158 +0,0 @@
"""
Support for Neato botvac connected vacuum cleaners.
For more details about this component, please refer to the documentation at
https://home-assistant.io/components/neato/
"""
import logging
from datetime import timedelta
from urllib.error import HTTPError
import voluptuous as vol
import homeassistant.helpers.config_validation as cv
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME
from homeassistant.helpers import discovery
from homeassistant.util import Throttle
_LOGGER = logging.getLogger(__name__)
REQUIREMENTS = ['https://github.com/dshokouhi/pybotvac/archive/0.0.8.zip'
'#pybotvac==0.0.8']
DOMAIN = 'neato'
NEATO_ROBOTS = 'neato_robots'
NEATO_LOGIN = 'neato_login'
NEATO_MAP_DATA = 'neato_map_data'
CONFIG_SCHEMA = vol.Schema({
DOMAIN: vol.Schema({
vol.Required(CONF_USERNAME): cv.string,
vol.Required(CONF_PASSWORD): cv.string,
})
}, extra=vol.ALLOW_EXTRA)
STATES = {
1: 'Idle',
2: 'Busy',
3: 'Pause',
4: 'Error'
}
MODE = {
1: 'Eco',
2: 'Turbo'
}
ACTION = {
0: 'No action',
1: 'House cleaning',
2: 'Spot cleaning',
3: 'Manual cleaning',
4: 'Docking',
5: 'User menu active',
6: 'Cleaning cancelled',
7: 'Updating...',
8: 'Copying logs...',
9: 'Calculating position...',
10: 'IEC test',
11: 'Map cleaning',
12: 'Exploring map (creating a persistent map)',
13: 'Acquiring Persistent Map IDs',
14: 'Creating & Uploading Map',
15: 'Suspended Exploration'
}
ERRORS = {
'ui_error_brush_stuck': 'Brush stuck',
'ui_error_brush_overloaded': 'Brush overloaded',
'ui_error_bumper_stuck': 'Bumper stuck',
'ui_error_dust_bin_missing': 'Dust bin missing',
'ui_error_dust_bin_full': 'Dust bin full',
'ui_error_dust_bin_emptied': 'Dust bin emptied',
'ui_error_navigation_backdrop_leftbump': 'Clear my path',
'ui_error_navigation_noprogress': 'Clear my path',
'ui_error_navigation_origin_unclean': 'Clear my path',
'ui_error_navigation_pathproblems_returninghome': 'Cannot return to base',
'ui_error_navigation_falling': 'Clear my path',
'ui_error_picked_up': 'Picked up',
'ui_error_stuck': 'Stuck!',
'dustbin_full': 'Dust bin full',
'dustbin_missing': 'Dust bin missing',
'maint_brush_stuck': 'Brush stuck',
'maint_brush_overload': 'Brush overloaded',
'maint_bumper_stuck': 'Bumper stuck',
'maint_vacuum_stuck': 'Vacuum is stuck',
'maint_left_drop_stuck': 'Vacuum is stuck',
'maint_left_wheel_stuck': 'Vacuum is stuck',
'maint_right_drop_stuck': 'Vacuum is stuck',
'maint_right_wheel_stuck': 'Vacuum is stuck',
'not_on_charge_base': 'Not on the charge base',
'nav_robot_falling': 'Clear my path',
'nav_no_path': 'Clear my path',
'nav_path_problem': 'Clear my path'
}
ALERTS = {
'ui_alert_dust_bin_full': 'Please empty dust bin',
'ui_alert_recovering_location': 'Returning to start',
'dustbin_full': 'Please empty dust bin',
'maint_brush_change': 'Change the brush',
'maint_filter_change': 'Change the filter'
}
def setup(hass, config):
"""Set up the Neato component."""
from pybotvac import Account
hass.data[NEATO_LOGIN] = NeatoHub(hass, config[DOMAIN], Account)
hub = hass.data[NEATO_LOGIN]
if not hub.login():
_LOGGER.debug("Failed to login to Neato API")
return False
hub.update_robots()
for component in ('camera', 'vacuum', 'switch'):
discovery.load_platform(hass, component, DOMAIN, {}, config)
return True
class NeatoHub(object):
"""A My Neato hub wrapper class."""
def __init__(self, hass, domain_config, neato):
"""Initialize the Neato hub."""
self.config = domain_config
self._neato = neato
self._hass = hass
self.my_neato = neato(
domain_config[CONF_USERNAME],
domain_config[CONF_PASSWORD])
self._hass.data[NEATO_ROBOTS] = self.my_neato.robots
self._hass.data[NEATO_MAP_DATA] = self.my_neato.maps
def login(self):
"""Login to My Neato."""
try:
_LOGGER.debug("Trying to connect to Neato API")
self.my_neato = self._neato(
self.config[CONF_USERNAME], self.config[CONF_PASSWORD])
return True
except HTTPError:
_LOGGER.error("Unable to connect to Neato API")
return False
@Throttle(timedelta(seconds=60))
def update_robots(self):
"""Update the robot states."""
_LOGGER.debug("Running HUB.update_robots %s",
self._hass.data[NEATO_ROBOTS])
self._hass.data[NEATO_ROBOTS] = self.my_neato.robots
self._hass.data[NEATO_MAP_DATA] = self.my_neato.maps
def download_map(self, url):
"""Download a new map image."""
map_image_data = self.my_neato.get_map_image(url)
return map_image_data

View File

@ -1,102 +0,0 @@
"""
Support for Neato Connected Vacuums switches.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/switch.neato/
"""
import logging
import requests
from datetime import timedelta
from homeassistant.const import STATE_OFF, STATE_ON
from homeassistant.helpers.entity import ToggleEntity
from homeassistant.components.neato import NEATO_ROBOTS, NEATO_LOGIN
from homeassistant.util import Throttle
_LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['neato']
SWITCH_TYPE_SCHEDULE = 'schedule'
SWITCH_TYPES = {
SWITCH_TYPE_SCHEDULE: ['Schedule']
}
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up the Neato switches."""
dev = []
for robot in hass.data[NEATO_ROBOTS]:
for type_name in SWITCH_TYPES:
dev.append(NeatoConnectedSwitch(hass, robot, type_name))
_LOGGER.debug("Adding switches %s", dev)
add_devices(dev)
class NeatoConnectedSwitch(ToggleEntity):
"""Neato Connected Switches."""
def __init__(self, hass, robot, switch_type):
"""Initialize the Neato Connected switches."""
self.type = switch_type
self.robot = robot
self.neato = hass.data[NEATO_LOGIN]
self._robot_name = '{} {}'.format(
self.robot.name, SWITCH_TYPES[self.type][0])
try:
self._state = self.robot.state
except (requests.exceptions.ConnectionError,
requests.exceptions.HTTPError) as ex:
_LOGGER.warning("Neato connection error: %s", ex)
self._state = None
self._schedule_state = None
self._clean_state = None
@Throttle(timedelta(seconds=60))
def update(self):
"""Update the states of Neato switches."""
_LOGGER.debug("Running switch update")
self.neato.update_robots()
try:
self._state = self.robot.state
except (requests.exceptions.ConnectionError,
requests.exceptions.HTTPError) as ex:
_LOGGER.warning("Neato connection error: %s", ex)
self._state = None
return
_LOGGER.debug('self._state=%s', self._state)
if self.type == SWITCH_TYPE_SCHEDULE:
_LOGGER.debug("State: %s", self._state)
if self.robot.schedule_enabled:
self._schedule_state = STATE_ON
else:
self._schedule_state = STATE_OFF
_LOGGER.debug("Schedule state: %s", self._schedule_state)
@property
def name(self):
"""Return the name of the switch."""
return self._robot_name
@property
def available(self):
"""Return True if entity is available."""
return self._state
@property
def is_on(self):
"""Return true if switch is on."""
if self.type == SWITCH_TYPE_SCHEDULE:
if self._schedule_state == STATE_ON:
return True
return False
def turn_on(self, **kwargs):
"""Turn the switch on."""
if self.type == SWITCH_TYPE_SCHEDULE:
self.robot.enable_schedule()
def turn_off(self, **kwargs):
"""Turn the switch off."""
if self.type == SWITCH_TYPE_SCHEDULE:
self.robot.disable_schedule()

View File

@ -1,212 +0,0 @@
"""
Support for Neato Connected Vacuums.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/vacuum.neato/
"""
import logging
import requests
from datetime import timedelta
from homeassistant.const import STATE_OFF, STATE_ON
from homeassistant.components.vacuum import (
VacuumDevice, SUPPORT_BATTERY, SUPPORT_PAUSE, SUPPORT_RETURN_HOME,
SUPPORT_STATUS, SUPPORT_STOP, SUPPORT_TURN_OFF, SUPPORT_TURN_ON,
SUPPORT_MAP, ATTR_STATUS, ATTR_BATTERY_LEVEL, ATTR_BATTERY_ICON)
from homeassistant.components.neato import (
NEATO_ROBOTS, NEATO_LOGIN, NEATO_MAP_DATA, ACTION, ERRORS, MODE, ALERTS)
from homeassistant.util import Throttle
_LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['neato']
SUPPORT_NEATO = SUPPORT_BATTERY | SUPPORT_PAUSE | SUPPORT_RETURN_HOME | \
SUPPORT_STOP | SUPPORT_TURN_OFF | SUPPORT_TURN_ON | \
SUPPORT_STATUS | SUPPORT_MAP
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'
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up the Neato vacuum."""
dev = []
for robot in hass.data[NEATO_ROBOTS]:
dev.append(NeatoConnectedVacuum(hass, robot))
_LOGGER.debug("Adding vacuums %s", dev)
add_devices(dev, True)
class NeatoConnectedVacuum(VacuumDevice):
"""Representation of a Neato Connected Vacuum."""
def __init__(self, hass, robot):
"""Initialize the Neato Connected Vacuum."""
self.robot = robot
self.neato = hass.data[NEATO_LOGIN]
self._name = '{}'.format(self.robot.name)
self._status_state = None
self._clean_state = None
self._state = None
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
@Throttle(timedelta(seconds=60))
def update(self):
"""Update the states of Neato Vacuums."""
_LOGGER.debug("Running Neato Vacuums update")
self.neato.update_robots()
try:
self._state = self.robot.state
except (requests.exceptions.ConnectionError,
requests.exceptions.HTTPError) as ex:
_LOGGER.warning("Neato connection error: %s", ex)
self._state = None
return
_LOGGER.debug('self._state=%s', self._state)
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:
self._status_state = (
MODE.get(self._state['cleaning']['mode'])
+ ' ' + ACTION.get(self._state['action']))
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.robot.state['action'] == 1 or
self.robot.state['action'] == 2 or
self.robot.state['action'] == 11 or
self.robot.state['action'] == 12 or
self.robot.state['action'] == 3 and
self.robot.state['state'] == 2):
self._clean_state = STATE_ON
else:
self._clean_state = STATE_OFF
if not self._mapdata.get(self.robot.serial, {}).get('maps', []):
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'])
@property
def name(self):
"""Return the name of the device."""
return self._name
@property
def supported_features(self):
"""Flag vacuum cleaner robot features that are supported."""
return SUPPORT_NEATO
@property
def battery_level(self):
"""Return the battery level of the vacuum cleaner."""
return self._state['details']['charge']
@property
def status(self):
"""Return the status of the vacuum cleaner."""
return self._status_state
@property
def state_attributes(self):
"""Return the state attributes of the vacuum cleaner."""
data = {}
if self.status is not None:
data[ATTR_STATUS] = self.status
if self.battery_level is not None:
data[ATTR_BATTERY_LEVEL] = self.battery_level
data[ATTR_BATTERY_ICON] = self.battery_icon
if self.clean_time_start is not None:
data[ATTR_CLEAN_START] = self.clean_time_start
if self.clean_time_stop is not None:
data[ATTR_CLEAN_STOP] = self.clean_time_stop
if self.clean_area is not None:
data[ATTR_CLEAN_AREA] = self.clean_area
if self.clean_suspension_charge_count is not None:
data[ATTR_CLEAN_SUSP_COUNT] = (
self.clean_suspension_charge_count)
if self.clean_suspension_time is not None:
data[ATTR_CLEAN_SUSP_TIME] = self.clean_suspension_time
if self.clean_battery_start is not None:
data[ATTR_CLEAN_BATTERY_START] = self.clean_battery_start
if self.clean_battery_end is not None:
data[ATTR_CLEAN_BATTERY_END] = self.clean_battery_end
return data
def turn_on(self, **kwargs):
"""Turn the vacuum on and start cleaning."""
self.robot.start_cleaning()
@property
def is_on(self):
"""Return true if switch is on."""
return self._clean_state == STATE_ON
def turn_off(self, **kwargs):
"""Turn the switch off."""
self.robot.pause_cleaning()
self.robot.send_to_base()
def return_to_base(self, **kwargs):
"""Set the vacuum cleaner to return to the dock."""
self.robot.send_to_base()
def stop(self, **kwargs):
"""Stop the vacuum cleaner."""
self.robot.stop_cleaning()
def start_pause(self, **kwargs):
"""Start, pause or resume the cleaning task."""
if self._state['state'] == 1:
self.robot.start_cleaning()
elif self._state['state'] == 2 and\
ALERTS.get(self._state['error']) is None:
self.robot.pause_cleaning()
if self._state['state'] == 3:
self.robot.resume_cleaning()

View File

@ -38,19 +38,19 @@ sensor:
{% endif %}
{{ holiday }}
- platform: rest
resource: http://www.webcal.fi/cal.php?id=335&format=json&start_year=current_year&end_year=2020&tz=America%2FNew_York
name: Flag
scan_interval: 14400
value_template: >-
{% set is_flag_day = False %}
{%- for day_val in value_json -%}
{% set now_string = now().strftime('%Y-%m-%d') %}
{%- if day_val.date==now_string and day_val.flag_day==1 -%}
{% set is_flag_day = True %}
{%- endif -%}
{% endfor %}
{{is_flag_day}}
# - platform: rest
# resource: http://www.webcal.fi/cal.php?id=335&format=json&start_year=current_year&end_year=2020&tz=America%2FNew_York
# name: Flag
# scan_interval: 14400
# value_template: >-
# {% set is_flag_day = False %}
# {%- for day_val in value_json -%}
# {% set now_string = now().strftime('%Y-%m-%d') %}
# {%- if day_val.date==now_string and day_val.flag_day==1 -%}
# {% set is_flag_day = True %}
# {%- endif -%}
# {% endfor %}
# {{is_flag_day}}
###############################################################################
# Automation that notifies of a Holiday "state" change

16
config/packages/rachio.yaml Executable file
View File

@ -0,0 +1,16 @@
#-------------------------------------------
# @CCOSTAN
# Original Repo : https://github.com/CCOSTAN/Home-AssistantConfig
# Neato Support for D7 Connected Botvac - control my [Neato Vacuum](http://amzn.to/2kqnnqu) with Home Assistant.
#-------------------------------------------
######################################################################
## [Rachio Sprinkler system](http://amzn.to/2eoPKBW) - Smart Sprinkler controller
######################################################################
homeassistant:
# customize_glob:
# "*.carlojuice*":
# homebridge_hidden: True
# hidden: False
#-------------------------------------------
rachio:
api_key: !secret rachio_api

View File

@ -44,9 +44,9 @@
- platform: rest
scan_interval: 86400
resource: http://ip.jsontest.com
resource: http://icanhazip.com
name: External IP
value_template: '{{ value_json.ip }}'
value_template: '{{ value }}'
#############################################################################################################
### This part of the automation is hidden due to the IP address exposed ##

Binary file not shown.

Before

Width:  |  Height:  |  Size: 0 B

After

Width:  |  Height:  |  Size: 135 KiB