Skip to content

Instantly share code, notes, and snippets.

@bachya
Created August 1, 2017 23:30
Show Gist options
  • Save bachya/ba8f063e188bfda91ae4c7777dc1d148 to your computer and use it in GitHub Desktop.
Save bachya/ba8f063e188bfda91ae4c7777dc1d148 to your computer and use it in GitHub Desktop.
"""
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