Skip to content
This repository has been archived by the owner on Aug 25, 2023. It is now read-only.

Commit

Permalink
Add files via upload
Browse files Browse the repository at this point in the history
  • Loading branch information
LRvdLinden authored May 14, 2021
1 parent f81ce27 commit 29736b0
Showing 1 changed file with 225 additions and 0 deletions.
225 changes: 225 additions & 0 deletions config/custom_components/afvalinfo/sensor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
#!/usr/bin/env python3
"""
Sensor component for Afvalinfo
Author: Johnny Visser
ToDo: Add huisnummer toevoeging
"""

import voluptuous as vol
from datetime import datetime, date, timedelta
from dateutil.relativedelta import relativedelta
import urllib.error
from babel import Locale
from babel.dates import format_date, format_datetime, format_time
import re

from .const.const import (
MIN_TIME_BETWEEN_UPDATES,
_LOGGER,
CONF_CITY,
CONF_LOCATION,
CONF_POSTCODE,
CONF_STREET_NUMBER,
CONF_STREET_NUMBER_SUFFIX,
CONF_DATE_FORMAT,
CONF_TIMESPAN_IN_DAYS,
CONF_LOCALE,
CONF_ID,
SENSOR_PREFIX,
ATTR_LAST_UPDATE,
ATTR_HIDDEN,
ATTR_DAYS_UNTIL_COLLECTION_DATE,
ATTR_IS_COLLECTION_DATE_TODAY,
ATTR_YEAR_MONTH_DAY_DATE,
SENSOR_TYPES,
)

from .location.trashapi import TrashApiAfval
from .sensortomorrow import AfvalInfoTomorrowSensor
from .sensortoday import AfvalInfoTodaySensor

from homeassistant.components.sensor import PLATFORM_SCHEMA
import homeassistant.helpers.config_validation as cv
from homeassistant.const import CONF_RESOURCES
from homeassistant.util import Throttle
from homeassistant.helpers.entity import Entity

PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_RESOURCES, default=[]): vol.All(
cv.ensure_list, [vol.In(SENSOR_TYPES)]
),
vol.Optional(CONF_CITY, default=""): cv.string,
vol.Optional(CONF_LOCATION, default="sliedrecht"): cv.string,
vol.Required(CONF_POSTCODE, default="3361AB"): cv.string,
vol.Required(CONF_STREET_NUMBER, default="1"): cv.string,
vol.Optional(CONF_STREET_NUMBER_SUFFIX, default=""): cv.string,
vol.Optional(CONF_DATE_FORMAT, default = "%d-%m-%Y"): cv.string,
vol.Optional(CONF_TIMESPAN_IN_DAYS, default="365"): cv.string,
vol.Optional(CONF_LOCALE, default = "en"): cv.string,
vol.Optional(CONF_ID, default = ""): cv.string,
}
)


def setup_platform(hass, config, add_entities, discovery_info=None):
_LOGGER.debug("Setup Afvalinfo sensor")

location = config.get(CONF_CITY).lower().strip()
if len(location) == 0:
location = config.get(CONF_LOCATION).lower().strip()
postcode = config.get(CONF_POSTCODE).strip()
street_number = config.get(CONF_STREET_NUMBER)
street_number_suffix = config.get(CONF_STREET_NUMBER_SUFFIX)
date_format = config.get(CONF_DATE_FORMAT).strip()
timespan_in_days = config.get(CONF_TIMESPAN_IN_DAYS)
locale = config.get(CONF_LOCALE)
id_name = config.get(CONF_ID)

try:
resourcesMinusTodayAndTomorrow = config[CONF_RESOURCES].copy()
if "trash_type_today" in resourcesMinusTodayAndTomorrow:
resourcesMinusTodayAndTomorrow.remove("trash_type_today")
if "trash_type_tomorrow" in resourcesMinusTodayAndTomorrow:
resourcesMinusTodayAndTomorrow.remove("trash_type_tomorrow")

data = AfvalinfoData(location, postcode, street_number, street_number_suffix, resourcesMinusTodayAndTomorrow)
except urllib.error.HTTPError as error:
_LOGGER.error(error.reason)
return False

entities = []

for resource in config[CONF_RESOURCES]:
sensor_type = resource.lower()

#if sensor_type not in SENSOR_TYPES:
if sensor_type.title().lower() != "trash_type_today" and sensor_type.title().lower() != "trash_type_tomorrow":
entities.append(AfvalinfoSensor(data, sensor_type, date_format, timespan_in_days, locale, id_name))

#Add sensor -trash_type_today
if sensor_type.title().lower() == "trash_type_today":
today = AfvalInfoTodaySensor(data, sensor_type, entities, id_name)
entities.append(today)
#Add sensor -trash_type_tomorrow
if sensor_type.title().lower() == "trash_type_tomorrow":
tomorrow = AfvalInfoTomorrowSensor(data, sensor_type, entities, id_name)
entities.append(tomorrow)

add_entities(entities)


class AfvalinfoData(object):
def __init__(self, location, postcode, street_number, street_number_suffix, resources):
self.data = None
self.location = location
self.postcode = postcode
self.street_number = street_number
self.street_number_suffix = street_number_suffix
self.resources = resources

@Throttle(MIN_TIME_BETWEEN_UPDATES)
def update(self):
_LOGGER.debug("Updating Waste collection dates")
trashapi = ["aa en hunze", "aalsmeer", "aalten", "achtkarspelen", "alblasserdam", "albrandswaard", "alkmaar", "almelo", "almere", "alphen aan den rijn", "alphen-chaam", "altena", "ameland", "amersfoort", "amstelveen", "apeldoorn", "arnhem", "assen", "asten", "baarle-nassau", "baarn", "barendrecht", "barneveld", "beek", "beekdaelen", "beemster", "beesel", "berg en dal", "bergeijk", "bergen op zoom", "bergen", "berkelland", "bernheze", "best", "beuningen", "beverwijk", "bladel", "blaricum", "bloemendaal", "bodegraven-reeuwijk", "boekel", "borger-odoorn", "borne", "borsele", "boxmeer", "boxtel", "breda", "brielle", "bronckhorst", "brummen", "brunssum", "bunnik", "bunschoten", "buren", "capelle aan den ijssel", "castricum", "coevorden", "cranendonck", "cuijk", "culemborg", "dalfsen", "dantumadeel f", "de bilt", "de friese meren", "de ronde venen", "de wolden", "delft", "den haag", "den helder", "deurne", "deventer", "diemen", "dinkelland", "doesburg", "doetinchem", "dongen", "dordrecht", "drechterland", "drimmelen", "dronten", "druten", "duiven", "echt-susteren", "ede", "eemnes", "eemsdelta", "eersel", "eijsden-margraten", "eindhoven", "elburg", "emmen", "enkhuizen", "enschede", "epe", "ermelo", "etten-leur", "geertruidenberg", "geldrop-mierlo", "gemert-bakel", "gilze en rijen", "goeree-overflakkee", "goes", "goirle", "gooise meren", "gorinchem", "gouda", "grave", "groningen", "gulpen-wittem", "haaksbergen", "haarlem", "haarlemmermeer", "halderberge", "hardenberg", "harderwijk", "hardinxveld-giessendam", "harlingen", "hattem", "heemskerk", "heemstede", "heerde", "heerenveen", "heerhugowaard", "heerlen", "heeze-leende", "heiloo", "hellendoorn", "hellevoetsluis", "helmond", "hendrik-ido-ambacht", "hengelo", "het hogeland", "heumen", "heusden", "hillegom", "hilvarenbeek", "hilversum", "hoeksche waard", "hof van twente", "hollands kroon", "hoogeveen", "hoorn", "horst aan de maas", "houten", "huizen", "hulst", "ijsselstein", "kaag en braassem", "kampen", "kapelle", "katwijk", "kerkrade", "koggenland", "krimpen aan den ijssel", "krimpenerwaard", "laarbeek", "landerd", "landgraaf", "langedijk", "lansingerland", "laren", "leeuwarden", "leiden", "leiderdorp", "leidschendam-voorburg", "lelystad", "leudal", "leusden", "lingewaard", "lisse", "lochem", "loon op zand", "lopik", "losser", "maasdriel", "maasgouw", "maastricht", "medemblik", "meerssen", "meierijstad", "meppel", "middelburg", "midden-delfland", "midden-drenthe", "midden-groningen", "mill en sint hubert", "moerdijk", "molenlanden", "montferland", "montfoort", "mook en middelaar", "neder-betuwe", "nieuwegein", "nieuwkoop", "nijkerk", "nijmegen", "nissewaard", "noardeast fryslan", "noord-beveland", "noordenveld", "noordoostpolder", "noordwijk", "nuenen", "nunspeet", "oirschot", "oisterwijk", "oldambt", "oldebroek", "oldenzaal", "olst-wijhe", "ommen", "oost gelre", "oosterhout", "ooststellingwerf", "opmeer", "opsterland", "oss", "oude ijsselstreek", "oude pekela", "oudewater", "overbetuwe", "papendrecht", "peel en maas", "pijnacker-nootdorp", "purmerend", "putten", "raalte", "reimerswaal", "renkum", "renswoude", "reusel-de mierden", "rheden", "rhenen", "ridderkerk", "rijssen-holten", "rijswijk", "roerdalen", "roermond", "roosendaal", "rotterdam rozenburg", "rotterdam", "rucphen", "s-hertogenbosch", "schagen", "scherpenzeel", "schiedam", "schouwen-duiveland", "simpelveld", "sint anthonis", "sint-michielsgestel", "sittard-geleen", "sliedrecht", "sluis", "smallingerland", "soest", "someren", "son en breugel", "stadskanaal", "staphorst", "stede broec", "steenwijkerland", "stein", "stichtse vecht", "terneuzen", "terschelling", "teylingen", "tholen", "tiel", "tietjerksteradeel", "tilburg", "tubbergen", "twenterand", "tynaarlo", "uden", "uitgeest", "urk", "utrecht", "utrechtse heuvelrug", "vaals", "valkenburg aan de geul", "valkenswaard", "veendam", "veenendaal", "veere", "veldhoven", "velsen", "venlo", "venray", "vijfheerenlanden", "vlaardingen", "vlissingen", "voerendaal", "voorschoten", "voorst", "vught", "waadhoeke", "waalre", "waalwijk", "waddinxveen", "wageningen", "wassenaar", "waterland", "weesp", "west betuwe", "west maas en waal", "westerkwartier", "westerveld", "westervoort", "westerwolde", "westland", "weststellingwerf", "westvoorne", "wierden", "wijchen", "wijdemeren", "wijk bij duurstede", "winterswijk", "woensdrecht", "woerden", "wormerland", "woudenberg", "zaanstad", "zaltbommel", "zandvoort", "zeewolde", "zeist", "zevenaar", "zoetermeer", "zoeterwoude", "zuidplas", "zuidwest-friesland", "zundert", "zutphen", "zwartewaterland", "zwijndrecht", "zwolle"]
if self.location in trashapi:
self.data = TrashApiAfval().get_data(
self.location, self.postcode, self.street_number, self.street_number_suffix, self.resources
)

class AfvalinfoSensor(Entity):
def __init__(self, data, sensor_type, date_format, timespan_in_days, locale, id_name):
self.data = data
self.type = sensor_type
self.date_format = date_format
self.timespan_in_days = timespan_in_days
self.locale = locale
self._name = SENSOR_PREFIX + (id_name + " " if len(id_name) > 0 else "") + SENSOR_TYPES[sensor_type][0]
self._icon = SENSOR_TYPES[sensor_type][1]
self._hidden = False
self._state = None
self._last_update = None
self._days_until_collection_date = None
self._is_collection_date_today = False
self._year_month_day_date = None

@property
def name(self):
return self._name

@property
def icon(self):
return self._icon

@property
def state(self):
return self._state

@property
def device_state_attributes(self):
return {ATTR_YEAR_MONTH_DAY_DATE: self._year_month_day_date, ATTR_LAST_UPDATE: self._last_update, ATTR_HIDDEN: self._hidden, ATTR_DAYS_UNTIL_COLLECTION_DATE: self._days_until_collection_date, ATTR_IS_COLLECTION_DATE_TODAY: self._is_collection_date_today}

@Throttle(MIN_TIME_BETWEEN_UPDATES)
def update(self):
self.data.update()
waste_data = self.data.data

try:
if waste_data:
if self.type in waste_data:
collection_date = datetime.strptime(
waste_data[self.type], "%Y-%m-%d"
).date()

# Date in date format "%Y-%m-%d"
self._year_month_day_date = str(collection_date)

if collection_date:
# Set the values of the sensor
self._last_update = datetime.today().strftime("%d-%m-%Y %H:%M")

# Is the collection date today?
self._is_collection_date_today = date.today() == collection_date

# Days until collection date
delta = collection_date - date.today()
self._days_until_collection_date = delta.days

# Only show the value if the date is lesser than or equal to (today + timespan_in_days)
if collection_date <= date.today() + relativedelta(days=int(self.timespan_in_days)):
#if the date does not contain a named day or month, return the date as normal
if (self.date_format.find('a') == -1 and self.date_format.find('A') == -1
and self.date_format.find('b') == -1 and self.date_format.find('B') == -1):
self._state = collection_date.strftime(self.date_format)
#else convert the named values to the locale names
else:
edited_date_format = self.date_format.replace('%a', 'EEE')
edited_date_format = edited_date_format.replace('%A', 'EEEE')
edited_date_format = edited_date_format.replace('%b', 'MMM')
edited_date_format = edited_date_format.replace('%B', 'MMMM')

#half babel, half date string... something like EEEE 04-MMMM-2020
half_babel_half_date = collection_date.strftime(edited_date_format)

#replace the digits with qquoted digits 01 --> '01'
half_babel_half_date = re.sub(r"(\d+)", r"'\1'", half_babel_half_date)
#transform the EEE, EEEE etc... to a real locale date, with babel
locale_date = format_date(collection_date, half_babel_half_date, locale=self.locale)

self._state = locale_date
else:
self._hidden = True
else:
raise ValueError()
else:
raise ValueError()
else:
raise ValueError()
except ValueError:
self._state = None
self._hidden = True
self._days_until_collection_date = None
self._year_month_day_date = None
self._is_collection_date_today = False
self._last_update = datetime.today().strftime("%d-%m-%Y %H:%M")

0 comments on commit 29736b0

Please sign in to comment.