From b66be59598c3d47413e2eb4d516216f8b52a3e09 Mon Sep 17 00:00:00 2001
From: Mick Vleeshouwer <mick@imick.nl>
Date: Wed, 2 May 2018 20:37:41 +0200
Subject: [PATCH] Add PostNL sensor (Dutch Postal Services) (#12366)

* Add basic PostNL sensor (WIP)

* Update PostNL sensor

* Bump version

* Small updates to PostNL package based on feedback

* Remove unused import

* Pass api to sensor

* Refactor based on feedback

* Update based on feedback

* Fix feedback

* Clean up

* Bugfiix

* Bugfix

* SCAN_INTERVAL fix

* Remove unused import

* Refactor for new wrapper implementation

* Update postnl package requirement

* Change throttle logic

* Update package version

* Add new line

* Minor changes

* Change refresh time to 30 minutes

* Update requirements_all.txt
---
 .coveragerc                               |   1 +
 homeassistant/components/sensor/postnl.py | 110 ++++++++++++++++++++++
 requirements_all.txt                      |   3 +
 3 files changed, 114 insertions(+)
 create mode 100644 homeassistant/components/sensor/postnl.py

diff --git a/.coveragerc b/.coveragerc
index 94722666c05..cf7a5a2cd9c 100644
--- a/.coveragerc
+++ b/.coveragerc
@@ -640,6 +640,7 @@ omit =
     homeassistant/components/sensor/plex.py
     homeassistant/components/sensor/pocketcasts.py
     homeassistant/components/sensor/pollen.py
+    homeassistant/components/sensor/postnl.py
     homeassistant/components/sensor/pushbullet.py
     homeassistant/components/sensor/pvoutput.py
     homeassistant/components/sensor/pyload.py
diff --git a/homeassistant/components/sensor/postnl.py b/homeassistant/components/sensor/postnl.py
new file mode 100644
index 00000000000..c38f58b7916
--- /dev/null
+++ b/homeassistant/components/sensor/postnl.py
@@ -0,0 +1,110 @@
+"""
+Sensor for PostNL packages.
+
+For more details about this platform, please refer to the documentation at
+https://home-assistant.io/components/sensor.postnl/
+"""
+from datetime import timedelta
+import logging
+
+import voluptuous as vol
+
+from homeassistant.components.sensor import PLATFORM_SCHEMA
+from homeassistant.const import (
+    ATTR_ATTRIBUTION, CONF_NAME, CONF_PASSWORD, CONF_USERNAME)
+import homeassistant.helpers.config_validation as cv
+from homeassistant.helpers.entity import Entity
+from homeassistant.util import Throttle
+
+REQUIREMENTS = ['postnl_api==1.0.1']
+
+_LOGGER = logging.getLogger(__name__)
+
+ATTRIBUTION = 'Information provided by PostNL'
+
+DEFAULT_NAME = 'postnl'
+
+ICON = 'mdi:package-variant-closed'
+
+MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=30)
+
+PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
+    vol.Required(CONF_USERNAME): cv.string,
+    vol.Required(CONF_PASSWORD): cv.string,
+    vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
+})
+
+
+# pylint: disable=unused-argument
+def setup_platform(hass, config, add_devices, discovery_info=None):
+    """Set up the PostNL sensor platform."""
+    from postnl_api import PostNL_API, UnauthorizedException
+
+    username = config.get(CONF_USERNAME)
+    password = config.get(CONF_PASSWORD)
+    name = config.get(CONF_NAME)
+
+    try:
+        api = PostNL_API(username, password)
+
+    except UnauthorizedException:
+        _LOGGER.exception("Can't connect to the PostNL webservice")
+        return
+
+    add_devices([PostNLSensor(api, name)], True)
+
+
+class PostNLSensor(Entity):
+    """Representation of a PostNL sensor."""
+
+    def __init__(self, api, name):
+        """Initialize the PostNL sensor."""
+        self._name = name
+        self._attributes = None
+        self._state = None
+        self._api = api
+
+    @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 'package(s)'
+
+    @property
+    def device_state_attributes(self):
+        """Return the state attributes."""
+        return self._attributes
+
+    @property
+    def icon(self):
+        """Icon to use in the frontend."""
+        return ICON
+
+    @Throttle(MIN_TIME_BETWEEN_UPDATES)
+    def update(self):
+        """Update device state."""
+        shipments = self._api.get_relevant_shipments()
+        status_counts = {}
+
+        for shipment in shipments:
+            status = shipment['status']['formatted']['short']
+            status = self._api.parse_datetime(status, '%d-%m-%Y', '%H:%M')
+
+            name = shipment['settings']['title']
+            status_counts[name] = status
+
+        self._attributes = {
+            ATTR_ATTRIBUTION: ATTRIBUTION,
+            **status_counts
+        }
+
+        self._state = len(status_counts)
diff --git a/requirements_all.txt b/requirements_all.txt
index 16f6001d576..1283011d7ac 100644
--- a/requirements_all.txt
+++ b/requirements_all.txt
@@ -632,6 +632,9 @@ pmsensor==0.4
 # homeassistant.components.sensor.pocketcasts
 pocketcasts==0.1
 
+# homeassistant.components.sensor.postnl
+postnl_api==1.0.1
+
 # homeassistant.components.climate.proliphix
 proliphix==0.4.1
 
-- 
GitLab