Created
August 1, 2017 23:30
-
-
Save bachya/ba8f063e188bfda91ae4c7777dc1d148 to your computer and use it in GitHub Desktop.
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
""" | |
File: denvertrash.py | |
Author: Aaron Bach | |
Email: [email protected] | |
""" | |
import datetime | |
import logging | |
import os | |
import voluptuous as vol | |
import yaml | |
import homeassistant.helpers.config_validation as cv | |
from homeassistant.components.sensor import PLATFORM_SCHEMA | |
from homeassistant.const import CONF_MONITORED_CONDITIONS | |
from homeassistant.helpers.entity import Entity | |
from homeassistant.util import Throttle | |
_LOGGER = logging.getLogger(__name__) | |
REQUIREMENTS = ['pyden==0.3.1'] | |
MIN_TIME_BETWEEN_UPDATES = datetime.timedelta(minutes=1) | |
PICKUP_TYPES = { | |
'compost': ('Compost Pickup', 'mdi:food-apple'), | |
'extra_trash': ('Extra Trash Pickup', 'mdi:truck'), | |
'recycling': ('Recycling Pickup', 'mdi:recycle'), | |
'trash': ('Trash Pickup', 'mdi:delete') | |
} | |
YAML_TRASH = 'denver_trash.yaml' | |
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ | |
vol.Optional(CONF_MONITORED_CONDITIONS, default=[]): | |
vol.All(cv.ensure_list, [vol.In(PICKUP_TYPES)]), | |
}) | |
class DenverTrashSensor(Entity): | |
""" A class representation of our sensor """ | |
def __init__(self, name, pickup_type, icon, update_method): | |
""" Initialize! """ | |
self._icon = icon | |
self._name = name | |
self._pickup_type = pickup_type | |
self._state = None | |
self._update_method = update_method | |
@property | |
def icon(self): | |
""" Returns the icon of the pickup type """ | |
return self._icon | |
@property | |
def name(self): | |
""" Returns the name of the pickup type """ | |
return self._name | |
@property | |
def state(self): | |
""" Returns the next pickup date of the pickup type """ | |
return self._state | |
@Throttle(MIN_TIME_BETWEEN_UPDATES) | |
def update(self): | |
""" Updates the status """ | |
import arrow | |
_LOGGER.debug('Updating sensor: %s', self._name) | |
present = arrow.utcnow() | |
next_pickup = arrow.get(self._update_method(self._pickup_type)) | |
if (next_pickup - present).days < 7: | |
self._state = next_pickup.humanize(present) | |
else: | |
self._state = next_pickup.format('MMMM DD, YYYY') | |
def setup_platform(hass, config, add_devices, discovery_info=None): | |
""" Setup! """ | |
import pyden | |
pickups_to_watch = config.get(CONF_MONITORED_CONDITIONS) | |
_LOGGER.debug('Pickup types being monitored: %s', pickups_to_watch) | |
client = None | |
config_data = {} | |
config_filepath = hass.config.path(YAML_TRASH) | |
latitude = hass.config.latitude | |
longitude = hass.config.longitude | |
place_id = None | |
# Option #1: Find place ID from config file: | |
try: | |
with open(config_filepath) as outfile: | |
if os.stat(config_filepath).st_size > 0: | |
config_data = yaml.load(outfile) | |
place_id = config_data.get('place_id') | |
except FileNotFoundError: | |
pass | |
except Exception as exc_info: # pylint: disable=broad-except | |
_LOGGER.error('Invalid data in config file; stopping platform...') | |
_LOGGER.debug(str(exc_info)) | |
return False | |
# Option #2: Find place ID from lat/long: | |
if place_id: | |
_LOGGER.debug('Loading place ID from config file: %s', place_id) | |
client = pyden.TrashClient.from_place_id(place_id) | |
else: | |
_LOGGER.debug('Place ID not found; creating from coordinates...') | |
try: | |
client = pyden.TrashClient.from_coordinates(latitude, longitude) | |
with open(config_filepath, 'w') as outfile: | |
config_data['place_id'] = client.place_id | |
yaml.dump(config_data, outfile, default_flow_style=False) | |
_LOGGER.debug('Place ID saved to config file') | |
except pyden.exceptions.GeocodingError as exc_info: | |
_LOGGER.error('An error occurred while geocoding: %s', | |
str(exc_info)) | |
return False | |
except pyden.exceptions.HTTPError as exc_info: | |
_LOGGER.error('An HTTP error occurred: %s', str(exc_info)) | |
return False | |
except Exception as exc_info: # pylint: disable=broad-except | |
_LOGGER.error('An unknown error occurred...') | |
_LOGGER.debug(str(exc_info)) | |
return False | |
# Grab schedule data from the client: | |
schedule = client.schedule() | |
_LOGGER.debug('Retrieved schedule data: %s', schedule) | |
sensors = [] | |
for pickup_type in pickups_to_watch: | |
name, icon = PICKUP_TYPES[pickup_type] | |
sensors.append( | |
DenverTrashSensor(name, pickup_type, icon, client.next_pickup)) | |
add_devices(sensors, True) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment