Add AfterShip sensor for packages (#18034)
* Add AfterShip sensor for packages Why: * I receive a lot of packages from many different shipping companies. * I would like to see in haas how many packages are being delivered. This change addreses the need by: * Adding a sensor for AfterShip (aftership.com) * AfterShip supports ~490 couriers world wide thus should cover almost any sensible tracking. Notes: - For now this sensor assumes you somehow have added trackings to aftership manually. - Future idea is to expose service that allows adding a tracking based on incoming mails. - Other improvments would be to add map markers for package locations. Related: - https://community.home-assistant.io/t/package-tracking/858 - https://community.home-assistant.io/t/aftership-package-tracking/24068 - https://community.home-assistant.io/t/aftership-shipment-tracking-platform/14074 - https://community.home-assistant.io/t/aftership-state-card/57912 * Fix typo and update ordering
This commit is contained in:
parent
d05450487c
commit
b32e6fe0d5
3 changed files with 132 additions and 0 deletions
|
@ -693,6 +693,7 @@ omit =
|
|||
homeassistant/components/route53.py
|
||||
homeassistant/components/scene/hunterdouglas_powerview.py
|
||||
homeassistant/components/scene/lifx_cloud.py
|
||||
homeassistant/components/sensor/aftership.py
|
||||
homeassistant/components/sensor/airvisual.py
|
||||
homeassistant/components/sensor/alpha_vantage.py
|
||||
homeassistant/components/sensor/ambient_station.py
|
||||
|
|
128
homeassistant/components/sensor/aftership.py
Normal file
128
homeassistant/components/sensor/aftership.py
Normal file
|
@ -0,0 +1,128 @@
|
|||
"""
|
||||
Support for non-delivered packages recorded in AfterShip.
|
||||
|
||||
For more details about this platform, please refer to the documentation at
|
||||
https://www.home-assistant.io/components/sensor.aftership/
|
||||
"""
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.sensor import PLATFORM_SCHEMA
|
||||
from homeassistant.const import ATTR_ATTRIBUTION, CONF_API_KEY, CONF_NAME
|
||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.util import Throttle
|
||||
|
||||
REQUIREMENTS = ['pyaftership==0.1.2']
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
ATTRIBUTION = 'Information provided by AfterShip'
|
||||
|
||||
CONF_SLUG = 'slug'
|
||||
CONF_TITLE = 'title'
|
||||
CONF_TRACKING_NUMBER = 'tracking_number'
|
||||
|
||||
DEFAULT_NAME = 'aftership'
|
||||
|
||||
ICON = 'mdi:package-variant-closed'
|
||||
|
||||
MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=30)
|
||||
|
||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
vol.Required(CONF_API_KEY): cv.string,
|
||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
||||
})
|
||||
|
||||
|
||||
async def async_setup_platform(
|
||||
hass, config, async_add_entities, discovery_info=None):
|
||||
"""Set up the AfterShip sensor platform."""
|
||||
from pyaftership.tracker import Tracking
|
||||
|
||||
apikey = config[CONF_API_KEY]
|
||||
name = config[CONF_NAME]
|
||||
|
||||
session = async_get_clientsession(hass)
|
||||
aftership = Tracking(hass.loop, session, apikey)
|
||||
|
||||
await aftership.get_trackings()
|
||||
|
||||
if not aftership.meta or aftership.meta['code'] != 200:
|
||||
_LOGGER.error("No tracking data found. Check API key is correct: %s",
|
||||
aftership.meta)
|
||||
return
|
||||
|
||||
async_add_entities([AfterShipSensor(aftership, name)], True)
|
||||
|
||||
|
||||
class AfterShipSensor(Entity):
|
||||
"""Representation of a AfterShip sensor."""
|
||||
|
||||
def __init__(self, aftership, name):
|
||||
"""Initialize the sensor."""
|
||||
self._attributes = {}
|
||||
self._name = name
|
||||
self._state = None
|
||||
self.aftership = aftership
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name of the sensor."""
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
"""Return the state of the sensor."""
|
||||
return self._state
|
||||
|
||||
@property
|
||||
def unit_of_measurement(self):
|
||||
"""Return the unit of measurement of this entity, if any."""
|
||||
return 'packages'
|
||||
|
||||
@property
|
||||
def device_state_attributes(self):
|
||||
"""Return attributes for the sensor."""
|
||||
return self._attributes
|
||||
|
||||
@property
|
||||
def icon(self):
|
||||
"""Icon to use in the frontend."""
|
||||
return ICON
|
||||
|
||||
@Throttle(MIN_TIME_BETWEEN_UPDATES)
|
||||
async def async_update(self):
|
||||
"""Get the latest data from the AfterShip API."""
|
||||
await self.aftership.get_trackings()
|
||||
|
||||
if not self.aftership.meta:
|
||||
_LOGGER.error("Unknown errors when querying")
|
||||
return
|
||||
if self.aftership.meta['code'] != 200:
|
||||
_LOGGER.error(
|
||||
"Errors when querying AfterShip. %s", str(self.aftership.meta))
|
||||
return
|
||||
|
||||
status_to_ignore = {'delivered'}
|
||||
status_counts = {}
|
||||
not_delivered_count = 0
|
||||
|
||||
for tracking in self.aftership.trackings['trackings']:
|
||||
status = tracking['tag'].lower()
|
||||
name = tracking['tracking_number']
|
||||
status_counts[status] = status_counts.get(status, 0)+1
|
||||
if status not in status_to_ignore:
|
||||
not_delivered_count += 1
|
||||
else:
|
||||
_LOGGER.debug("Ignoring %s as it has status: %s", name, status)
|
||||
|
||||
self._attributes = {
|
||||
ATTR_ATTRIBUTION: ATTRIBUTION,
|
||||
**status_counts
|
||||
}
|
||||
|
||||
self._state = not_delivered_count
|
|
@ -881,6 +881,9 @@ pyW800rf32==0.1
|
|||
# homeassistant.components.ads
|
||||
pyads==2.2.6
|
||||
|
||||
# homeassistant.components.sensor.aftership
|
||||
pyaftership==0.1.2
|
||||
|
||||
# homeassistant.components.sensor.airvisual
|
||||
pyairvisual==2.0.1
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue