Add Avri waste collection sensor (#31134)
* Add Avri waste collection sensor * Apply black formatting * Update manifest * Add requirements * Add sensor to coverage * Update import order * Bump dependency to include todays pickup * Bump avri version in requirements_all.txt * Code review comments * Reduce scan interval to 4 hours This makes sure that no matter what happens, in the morning the correct dates have been pulled without the old ones lingering for too long. * Better logging * Made scan interval a timedelta * Fix import order * Update homeassistant/components/avri/sensor.py Co-Authored-By: springstan <46536646+springstan@users.noreply.github.com> * Update homeassistant/components/avri/sensor.py Co-Authored-By: springstan <46536646+springstan@users.noreply.github.com> * Use filter instead of break statement * Use positive int for house number extension * Switch voluptuous types for house number and house number extension * Update homeassistant/components/avri/sensor.py Co-Authored-By: Paulus Schoutsen <paulus@home-assistant.io> * Implement `available` * Bump avri api * Code review comments * Replace `postcode` with `zip_code` * Update logic for `available` * Remove variable for delimiter Co-authored-by: springstan <46536646+springstan@users.noreply.github.com> Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>
This commit is contained in:
parent
02c170b961
commit
1d962aeb65
6 changed files with 130 additions and 0 deletions
|
@ -65,6 +65,7 @@ omit =
|
||||||
homeassistant/components/automatic/device_tracker.py
|
homeassistant/components/automatic/device_tracker.py
|
||||||
homeassistant/components/avea/light.py
|
homeassistant/components/avea/light.py
|
||||||
homeassistant/components/avion/light.py
|
homeassistant/components/avion/light.py
|
||||||
|
homeassistant/components/avri/sensor.py
|
||||||
homeassistant/components/azure_event_hub/*
|
homeassistant/components/azure_event_hub/*
|
||||||
homeassistant/components/azure_service_bus/*
|
homeassistant/components/azure_service_bus/*
|
||||||
homeassistant/components/baidu/tts.py
|
homeassistant/components/baidu/tts.py
|
||||||
|
|
|
@ -41,6 +41,7 @@ homeassistant/components/auth/* @home-assistant/core
|
||||||
homeassistant/components/automatic/* @armills
|
homeassistant/components/automatic/* @armills
|
||||||
homeassistant/components/automation/* @home-assistant/core
|
homeassistant/components/automation/* @home-assistant/core
|
||||||
homeassistant/components/avea/* @pattyland
|
homeassistant/components/avea/* @pattyland
|
||||||
|
homeassistant/components/avri/* @timvancann
|
||||||
homeassistant/components/awair/* @danielsjf
|
homeassistant/components/awair/* @danielsjf
|
||||||
homeassistant/components/aws/* @awarecan @robbiet480
|
homeassistant/components/aws/* @awarecan @robbiet480
|
||||||
homeassistant/components/axis/* @kane610
|
homeassistant/components/axis/* @kane610
|
||||||
|
|
1
homeassistant/components/avri/__init__.py
Normal file
1
homeassistant/components/avri/__init__.py
Normal file
|
@ -0,0 +1 @@
|
||||||
|
"""The avri component."""
|
8
homeassistant/components/avri/manifest.json
Normal file
8
homeassistant/components/avri/manifest.json
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"domain": "avri",
|
||||||
|
"name": "Avri",
|
||||||
|
"documentation": "https://www.home-assistant.io/integrations/avri",
|
||||||
|
"requirements": ["avri-api==0.1.6"],
|
||||||
|
"dependencies": [],
|
||||||
|
"codeowners": ["@timvancann"]
|
||||||
|
}
|
116
homeassistant/components/avri/sensor.py
Normal file
116
homeassistant/components/avri/sensor.py
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
"""Support for Avri waste curbside collection pickup."""
|
||||||
|
from datetime import timedelta
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from avri.api import Avri, AvriException
|
||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
|
from homeassistant.components.sensor import PLATFORM_SCHEMA
|
||||||
|
from homeassistant.const import CONF_NAME
|
||||||
|
from homeassistant.exceptions import PlatformNotReady
|
||||||
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
from homeassistant.helpers.entity import Entity
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
CONF_COUNTRY_CODE = "country_code"
|
||||||
|
CONF_ZIP_CODE = "zip_code"
|
||||||
|
CONF_HOUSE_NUMBER = "house_number"
|
||||||
|
CONF_HOUSE_NUMBER_EXTENSION = "house_number_extension"
|
||||||
|
DEFAULT_NAME = "avri"
|
||||||
|
ICON = "mdi:trash-can-outline"
|
||||||
|
SCAN_INTERVAL = timedelta(hours=4)
|
||||||
|
DEFAULT_COUNTRY_CODE = "NL"
|
||||||
|
|
||||||
|
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
||||||
|
{
|
||||||
|
vol.Required(CONF_ZIP_CODE): cv.string,
|
||||||
|
vol.Required(CONF_HOUSE_NUMBER): cv.positive_int,
|
||||||
|
vol.Optional(CONF_HOUSE_NUMBER_EXTENSION): cv.string,
|
||||||
|
vol.Optional(CONF_COUNTRY_CODE, default=DEFAULT_COUNTRY_CODE): cv.string,
|
||||||
|
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||||
|
"""Set up the Avri Waste platform."""
|
||||||
|
client = Avri(
|
||||||
|
postal_code=config[CONF_ZIP_CODE],
|
||||||
|
house_nr=config[CONF_HOUSE_NUMBER],
|
||||||
|
house_nr_extension=config.get(CONF_HOUSE_NUMBER_EXTENSION),
|
||||||
|
country_code=config[CONF_COUNTRY_CODE],
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
each_upcoming = client.upcoming_of_each()
|
||||||
|
except AvriException as ex:
|
||||||
|
raise PlatformNotReady from ex
|
||||||
|
else:
|
||||||
|
entities = [
|
||||||
|
AvriWasteUpcoming(config[CONF_NAME], client, upcoming.name)
|
||||||
|
for upcoming in each_upcoming
|
||||||
|
]
|
||||||
|
add_entities(entities, True)
|
||||||
|
|
||||||
|
|
||||||
|
class AvriWasteUpcoming(Entity):
|
||||||
|
"""Avri Waste Sensor."""
|
||||||
|
|
||||||
|
def __init__(self, name: str, client: Avri, waste_type: str):
|
||||||
|
"""Initialize the sensor."""
|
||||||
|
self._waste_type = waste_type
|
||||||
|
self._name = f"{name}_{self._waste_type}"
|
||||||
|
self._state = None
|
||||||
|
self._client = client
|
||||||
|
self._state_available = False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
"""Return the name of the sensor."""
|
||||||
|
return self._name
|
||||||
|
|
||||||
|
@property
|
||||||
|
def unique_id(self) -> str:
|
||||||
|
"""Return a unique ID."""
|
||||||
|
return (
|
||||||
|
f"{self._waste_type}"
|
||||||
|
f"-{self._client.country_code}"
|
||||||
|
f"-{self._client.postal_code}"
|
||||||
|
f"-{self._client.house_nr}"
|
||||||
|
f"-{self._client.house_nr_extension}"
|
||||||
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def state(self):
|
||||||
|
"""Return the state of the sensor."""
|
||||||
|
return self._state
|
||||||
|
|
||||||
|
@property
|
||||||
|
def available(self):
|
||||||
|
"""Return True if entity is available."""
|
||||||
|
return self._state_available
|
||||||
|
|
||||||
|
@property
|
||||||
|
def icon(self):
|
||||||
|
"""Icon to use in the frontend."""
|
||||||
|
return ICON
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
"""Update device state."""
|
||||||
|
try:
|
||||||
|
pickup_events = self._client.upcoming_of_each()
|
||||||
|
except AvriException as ex:
|
||||||
|
_LOGGER.error(
|
||||||
|
"There was an error retrieving upcoming garbage pickups: %s", ex
|
||||||
|
)
|
||||||
|
self._state_available = False
|
||||||
|
self._state = None
|
||||||
|
else:
|
||||||
|
self._state_available = True
|
||||||
|
matched_events = list(
|
||||||
|
filter(lambda event: event.name == self._waste_type, pickup_events)
|
||||||
|
)
|
||||||
|
if not matched_events:
|
||||||
|
self._state = None
|
||||||
|
else:
|
||||||
|
self._state = matched_events[0].day.date()
|
|
@ -278,6 +278,9 @@ avea==1.4
|
||||||
# homeassistant.components.avion
|
# homeassistant.components.avion
|
||||||
# avion==0.10
|
# avion==0.10
|
||||||
|
|
||||||
|
# homeassistant.components.avri
|
||||||
|
avri-api==0.1.6
|
||||||
|
|
||||||
# homeassistant.components.axis
|
# homeassistant.components.axis
|
||||||
axis==25
|
axis==25
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue