-
-
Notifications
You must be signed in to change notification settings - Fork 28.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for Zillow Zestimate sensor (#12597)
* Added Zillow Zestimate sensor. * Add zestimate.py to .coveragerc * Fix line 167 81>80 * Incorporate tinloaf changes. * Saving work * Incorporate changes requested by MartinHjelmare * Remove unnecessary import * Add a blank line between standard library and 3rd party imports
- Loading branch information
1 parent
49581a4
commit a9d242a
Showing
3 changed files
with
136 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
""" | ||
Support for zestimate data from zillow.com. | ||
For more details about this platform, please refer to the documentation at | ||
https://home-assistant.io/components/sensor.zestimate/ | ||
""" | ||
from datetime import timedelta | ||
import logging | ||
|
||
import requests | ||
import voluptuous as vol | ||
|
||
from homeassistant.components.sensor import PLATFORM_SCHEMA | ||
from homeassistant.const import (CONF_API_KEY, | ||
CONF_NAME, ATTR_ATTRIBUTION) | ||
import homeassistant.helpers.config_validation as cv | ||
from homeassistant.helpers.entity import Entity | ||
from homeassistant.util import Throttle | ||
|
||
REQUIREMENTS = ['xmltodict==0.11.0'] | ||
|
||
_LOGGER = logging.getLogger(__name__) | ||
_RESOURCE = 'http://www.zillow.com/webservice/GetZestimate.htm' | ||
|
||
CONF_ZPID = 'zpid' | ||
CONF_ATTRIBUTION = "Data provided by Zillow.com" | ||
|
||
DEFAULT_NAME = 'Zestimate' | ||
NAME = 'zestimate' | ||
ZESTIMATE = '{}:{}'.format(DEFAULT_NAME, NAME) | ||
|
||
ICON = 'mdi:home-variant' | ||
|
||
ATTR_AMOUNT = 'amount' | ||
ATTR_CHANGE = 'amount_change_30_days' | ||
ATTR_CURRENCY = 'amount_currency' | ||
ATTR_LAST_UPDATED = 'amount_last_updated' | ||
ATTR_VAL_HI = 'valuation_range_high' | ||
ATTR_VAL_LOW = 'valuation_range_low' | ||
|
||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ | ||
vol.Required(CONF_API_KEY): cv.string, | ||
vol.Required(CONF_ZPID): vol.All(cv.ensure_list, [cv.string]), | ||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, | ||
}) | ||
|
||
|
||
# Return cached results if last scan was less then this time ago. | ||
MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=30) | ||
|
||
|
||
def setup_platform(hass, config, add_devices, discovery_info=None): | ||
"""Set up the Zestimate sensor.""" | ||
name = config.get(CONF_NAME) | ||
properties = config[CONF_ZPID] | ||
params = {'zws-id': config[CONF_API_KEY]} | ||
|
||
sensors = [] | ||
for zpid in properties: | ||
params['zpid'] = zpid | ||
sensors.append(ZestimateDataSensor(name, params)) | ||
add_devices(sensors, True) | ||
|
||
|
||
class ZestimateDataSensor(Entity): | ||
"""Implementation of a Zestimate sensor.""" | ||
|
||
def __init__(self, name, params): | ||
"""Initialize the sensor.""" | ||
self._name = name | ||
self.params = params | ||
self.data = None | ||
self.address = None | ||
self._state = None | ||
|
||
@property | ||
def name(self): | ||
"""Return the name of the sensor.""" | ||
return self._name | ||
|
||
@property | ||
def state(self): | ||
"""Return the state of the sensor.""" | ||
try: | ||
return round(float(self._state), 1) | ||
except ValueError: | ||
return None | ||
|
||
@property | ||
def device_state_attributes(self): | ||
"""Return the state attributes.""" | ||
attributes = {} | ||
if self.data is not None: | ||
attributes = self.data | ||
attributes['address'] = self.address | ||
attributes[ATTR_ATTRIBUTION] = CONF_ATTRIBUTION | ||
return attributes | ||
|
||
@property | ||
def icon(self): | ||
"""Icon to use in the frontend, if any.""" | ||
return ICON | ||
|
||
@Throttle(MIN_TIME_BETWEEN_UPDATES) | ||
def update(self): | ||
"""Get the latest data and update the states.""" | ||
import xmltodict | ||
try: | ||
response = requests.get(_RESOURCE, params=self.params, timeout=5) | ||
data = response.content.decode('utf-8') | ||
data_dict = xmltodict.parse(data).get(ZESTIMATE) | ||
error_code = int(data_dict['message']['code']) | ||
if error_code != 0: | ||
_LOGGER.error('The API returned: %s', | ||
data_dict['message']['text']) | ||
return | ||
except requests.exceptions.ConnectionError: | ||
_LOGGER.error('Unable to retrieve data from %s', _RESOURCE) | ||
return | ||
data = data_dict['response'][NAME] | ||
details = {} | ||
details[ATTR_AMOUNT] = data['amount']['#text'] | ||
details[ATTR_CURRENCY] = data['amount']['@currency'] | ||
details[ATTR_LAST_UPDATED] = data['last-updated'] | ||
details[ATTR_CHANGE] = int(data['valueChange']['#text']) | ||
details[ATTR_VAL_HI] = int(data['valuationRange']['high']['#text']) | ||
details[ATTR_VAL_LOW] = int(data['valuationRange']['low']['#text']) | ||
self.address = data_dict['response']['address']['street'] | ||
self.data = details | ||
if self.data is not None: | ||
self._state = self.data[ATTR_AMOUNT] | ||
else: | ||
self._state = None | ||
_LOGGER.error('Unable to parase Zestimate data from response') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters