diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 67dc70f..dc723d2 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,6 +1,5 @@ - blank_issues_enabled: false contact_links: - - name: ❔ Ask a question in the HASS community + - name: 🙋 Ask a question in the HASS community url: https://community.home-assistant.io/t/garbage-pickup-date-mijnafvalwijzer-nl-custom-component/34631 - about: If you are unsure where to go, then contacting the HASS community is recommended; Just ask! + about: If you are unsure where to go, then contacting the HASS community is recommended; Just ask! diff --git a/.github/ISSUE_TEMPLATE/issue.yml b/.github/ISSUE_TEMPLATE/issue.yml index 5c68070..e925739 100644 --- a/.github/ISSUE_TEMPLATE/issue.yml +++ b/.github/ISSUE_TEMPLATE/issue.yml @@ -1,42 +1,51 @@ name: 🚨 Report an issue description: Report an issue. body: - - type: markdown + - type: checkboxes attributes: - value: | - This issue form is for reporting bugs. + label: Support guidelines + description: Please read the support guidelines before proceeding. + options: + - label: I've read the [support guidelines](https://github.com/xirixiz/homeassistant-afvalwijzer/blob/master/.github/SUPPORT.md) + required: true + - type: textarea + attributes: + label: Description + description: Please provide a brief description of the issue in 1-2 sentences. validations: required: true - attributes: - label: Issue - description: >- - Describe the issue you are experiencing here to communicate to the - maintainers. Tell us what you were trying to do and what happened. - Provide a clear and concise description of what the problem is. - - type: input - id: version + - type: textarea + attributes: + label: Expected behaviour + description: Please describe precisely what you'd expect to happen. validations: required: true + + - type: textarea attributes: - label: Which version has the issue? - description: > - Can be found in the About section. - - type: input - attributes: - label: What was the last working version? - description: > - If known, otherwise leave blank. + label: Actual behaviour + description: Please describe precisely what is actually happening. + validations: + required: true + - type: textarea attributes: - label: Anything in the logs that might be useful? - description: For example, error message, or stack traces. - render: txt + label: Version + description: Please provide the HASS version, component version and system information (ARM, Docker, anything usefull). + value: | + * HASS version: + * Component version: + * Useful system info: + validations: + required: true + - type: textarea attributes: - label: Additional information - description: > - If you have any additional information, use the field below. - Please note, you can attach screenshots or screen recordings here, by - dragging and dropping files in the field below. + label: HASS logs + description: Please provide the HASS logs (preferably with debug enabled). + value: | + * logger -> logs -> custom_components.afvalwijzer: debug in you configuration.yaml + validations: + required: true diff --git a/.github/SUPPORT.md b/.github/SUPPORT.md new file mode 100644 index 0000000..1dab8e3 --- /dev/null +++ b/.github/SUPPORT.md @@ -0,0 +1,29 @@ +# Support [![](https://isitmaintained.com/badge/resolution/xirixiz/homeassistant-afvalwijzer.svg)](https://isitmaintained.com/project/xirixiz/homeassistant-afvalwijzer) + +## Reporting an issue + +Please do a search in [open issues](https://github.com/xirixiz/homeassistant-afvalwijzer/issues?utf8=%E2%9C%93&q=) to see if the issue or feature request has already been filed. + +If you find your issue already exists, make relevant comments and add your [reaction](https://github.com/blog/2119-add-reactions-to-pull-requests-issues-and-comments). Use a reaction in place of a "+1" comment. + +:+1: - upvote + +:-1: - downvote + +If you cannot find an existing issue that describes your bug or feature, submit an issue using the guidelines below. + +## Writing good bug reports and feature requests + +File a single issue per problem and feature request. + +* Do not enumerate multiple bugs or feature requests in the same issue. +* Do not add your issue as a comment to an existing issue unless it's for the identical input. Many issues look similar, but have different causes. + +The more information you can provide, the more likely someone will be successful reproducing the issue and finding a fix. + +You are now ready to [create a new issue](https://github.com/xirixiz/homeassistant-afvalwijzer/issues/new/choose)! + +## Closure policy + +* Issues that don't have the information requested above (when applicable) will be closed immediately and the poster directed to the support guidelines. +* Issues that go a week without a response from original poster are subject to closure at my discretion. diff --git a/custom_components/afvalwijzer/collector/mijnafvalwijzer.py b/custom_components/afvalwijzer/collector/mijnafvalwijzer.py index 4e728b1..906b3cc 100644 --- a/custom_components/afvalwijzer/collector/mijnafvalwijzer.py +++ b/custom_components/afvalwijzer/collector/mijnafvalwijzer.py @@ -1,6 +1,9 @@ from datetime import datetime + import requests +from ..common.day_sensor_data import DaySensorData +from ..common.next_sensor_data import NextSensorData from ..const.const import ( _LOGGER, DATE_TODAY, @@ -8,13 +11,18 @@ SENSOR_COLLECTOR_TO_URL, SENSOR_COLLECTORS_AFVALWIJZER, ) -from ..common.day_sensor_data import DaySensorData -from ..common.next_sensor_data import NextSensorData class MijnAfvalWijzerCollector(object): def __init__( - self, provider, postal_code, street_number, suffix, exclude_pickup_today, exclude_list, default_label + self, + provider, + postal_code, + street_number, + suffix, + exclude_pickup_today, + exclude_list, + default_label, ): self.provider = provider self.postal_code = postal_code @@ -62,7 +70,10 @@ def get_waste_data_provider(self): raise ValueError("No JSON data received from " + url) try: - waste_data_raw = json_response["ophaaldagen"]["data"] + json_response["ophaaldagenNext"]["data"] + waste_data_raw = ( + json_response["ophaaldagen"]["data"] + + json_response["ophaaldagenNext"]["data"] + ) except ValueError: raise ValueError("Invalid and/or no JSON data received from " + url) @@ -114,7 +125,13 @@ def transform_waste_data(self): try: waste_types_provider = sorted( - set(list(waste["type"] for waste in self.waste_data_raw if waste["type"] not in self.exclude_list)) + set( + list( + waste["type"] + for waste in self.waste_data_raw + if waste["type"] not in self.exclude_list + ) + ) ) except Exception as err: _LOGGER.error("Other error occurred waste_types_provider: %s", err) @@ -135,10 +152,14 @@ def transform_waste_data(self): try: waste_data_after_date_selected = list( - filter(lambda waste: waste["date"] >= date_selected, waste_data_formatted) + filter( + lambda waste: waste["date"] >= date_selected, waste_data_formatted + ) ) except Exception as err: - _LOGGER.error("Other error occurred waste_data_after_date_selected: %s", err) + _LOGGER.error( + "Other error occurred waste_data_after_date_selected: %s", err + ) next = NextSensorData(waste_data_after_date_selected, self.default_label) @@ -152,7 +173,12 @@ def transform_waste_data(self): except Exception as err: _LOGGER.error("Other error occurred waste_types_custom: %s", err) - return waste_data_provider, waste_types_provider, waste_data_custom, waste_types_custom + return ( + waste_data_provider, + waste_types_provider, + waste_data_custom, + waste_types_custom, + ) ########################################################################## # PROPERTIES FOR EXECUTION diff --git a/custom_components/afvalwijzer/collector/ximmio.py b/custom_components/afvalwijzer/collector/ximmio.py index 9c20789..6fd01e9 100644 --- a/custom_components/afvalwijzer/collector/ximmio.py +++ b/custom_components/afvalwijzer/collector/ximmio.py @@ -1,21 +1,29 @@ from datetime import datetime + import requests +from ..common.day_sensor_data import DaySensorData +from ..common.next_sensor_data import NextSensorData from ..const.const import ( _LOGGER, DATE_TODAY, - DATE_TOMORROW, DATE_TODAY_NEXT_YEAR, - SENSOR_COLLECTORS_XIMMIO, + DATE_TOMORROW, SENSOR_COLLECTOR_TO_URL, + SENSOR_COLLECTORS_XIMMIO, ) -from ..common.day_sensor_data import DaySensorData -from ..common.next_sensor_data import NextSensorData class XimmioCollector(object): def __init__( - self, provider, postal_code, street_number, suffix, exclude_pickup_today, exclude_list, default_label + self, + provider, + postal_code, + street_number, + suffix, + exclude_pickup_today, + exclude_list, + default_label, ): self.provider = provider self.postal_code = postal_code @@ -97,8 +105,12 @@ def get_waste_data_provider(self): for item in waste_data_raw: temp = {} - temp["type"] = self.__waste_type_rename(item["_pickupTypeText"].strip().lower()) - temp["date"] = datetime.strptime(item["pickupDates"][0], "%Y-%m-%dT%H:%M:%S").strftime("%Y-%m-%d") + temp["type"] = self.__waste_type_rename( + item["_pickupTypeText"].strip().lower() + ) + temp["date"] = datetime.strptime( + item["pickupDates"][0], "%Y-%m-%dT%H:%M:%S" + ).strftime("%Y-%m-%d") waste_data_raw_formatted.append(temp) for item in waste_data_raw_formatted: @@ -128,7 +140,11 @@ def get_waste_data_provider(self): except Exception as err: _LOGGER.error("Other error occurred: %s", err) - return waste_data_raw_formatted, waste_data_with_today, waste_data_without_today + return ( + waste_data_raw_formatted, + waste_data_with_today, + waste_data_without_today, + ) except Exception as err: _LOGGER.error("Other error occurred: %s", err) @@ -174,7 +190,13 @@ def transform_waste_data(self): try: waste_types_provider = sorted( - set(list(waste["type"] for waste in self.waste_data_raw if waste["type"] not in self.exclude_list)) + set( + list( + waste["type"] + for waste in self.waste_data_raw + if waste["type"] not in self.exclude_list + ) + ) ) except Exception as err: _LOGGER.error("Other error occurred waste_types_provider: %s", err) @@ -195,10 +217,14 @@ def transform_waste_data(self): try: waste_data_after_date_selected = list( - filter(lambda waste: waste["date"] >= date_selected, waste_data_formatted) + filter( + lambda waste: waste["date"] >= date_selected, waste_data_formatted + ) ) except Exception as err: - _LOGGER.error("Other error occurred waste_data_after_date_selected: %s", err) + _LOGGER.error( + "Other error occurred waste_data_after_date_selected: %s", err + ) next = NextSensorData(waste_data_after_date_selected, self.default_label) @@ -212,7 +238,12 @@ def transform_waste_data(self): except Exception as err: _LOGGER.error("Other error occurred waste_types_custom: %s", err) - return waste_data_provider, waste_types_provider, waste_data_custom, waste_types_custom + return ( + waste_data_provider, + waste_types_provider, + waste_data_custom, + waste_types_custom, + ) ########################################################################## # PROPERTIES FOR EXECUTION diff --git a/custom_components/afvalwijzer/common/day_sensor_data.py b/custom_components/afvalwijzer/common/day_sensor_data.py index b875a8b..c6ee48a 100644 --- a/custom_components/afvalwijzer/common/day_sensor_data.py +++ b/custom_components/afvalwijzer/common/day_sensor_data.py @@ -1,4 +1,4 @@ -from ..const.const import _LOGGER, DATE_TODAY, DATE_TOMORROW, DATE_DOT +from ..const.const import _LOGGER, DATE_DOT, DATE_TODAY, DATE_TOMORROW class DaySensorData(object): diff --git a/custom_components/afvalwijzer/const/const.py b/custom_components/afvalwijzer/const/const.py index b06f119..0faccc9 100755 --- a/custom_components/afvalwijzer/const/const.py +++ b/custom_components/afvalwijzer/const/const.py @@ -12,8 +12,12 @@ "afvalwijzer_data_default": [ "https://api.{0}.nl/webservices/appsinput/?apikey=5ef443e778f41c4f75c69459eea6e6ae0c2d92de729aa0fc61653815fbd6a8ca&method=postcodecheck&postcode={1}&street=&huisnummer={2}&toevoeging={3}&app_name=afvalwijzer&platform=phone&afvaldata={4}&langs=nl&" ], - "afvalstoffendienstkalender": ["https://{0}.afvalstoffendienstkalender.nl/nl/{1}/{2}/"], - "afvalstoffendienstkalender-s-hertogenbosch": ["https://afvalstoffendienstkalender.nl/nl/{0}/{1}/"], + "afvalstoffendienstkalender": [ + "https://{0}.afvalstoffendienstkalender.nl/nl/{1}/{2}/" + ], + "afvalstoffendienstkalender-s-hertogenbosch": [ + "https://afvalstoffendienstkalender.nl/nl/{0}/{1}/" + ], "ximmio01": [ "https://wasteapi.ximmio.com/api/FetchAdress", "https://wasteapi.ximmio.com/api/GetCalendar", diff --git a/custom_components/afvalwijzer/sensor.py b/custom_components/afvalwijzer/sensor.py index 52e9e1c..3d98f4d 100755 --- a/custom_components/afvalwijzer/sensor.py +++ b/custom_components/afvalwijzer/sensor.py @@ -4,39 +4,40 @@ Author: Bram van Dartel - xirixiz """ +from functools import partial + +from homeassistant.components.sensor import PLATFORM_SCHEMA +import homeassistant.helpers.config_validation as cv +from homeassistant.util import Throttle +import voluptuous as vol + +from .collector.mijnafvalwijzer import MijnAfvalWijzerCollector +from .collector.ximmio import XimmioCollector from .const.const import ( _LOGGER, + CONF_COLLECTOR, CONF_DEFAULT_LABEL, CONF_EXCLUDE_LIST, - CONF_ID, CONF_EXCLUDE_PICKUP_TODAY, + CONF_ID, CONF_POSTAL_CODE, - CONF_COLLECTOR, CONF_STREET_NUMBER, CONF_SUFFIX, MIN_TIME_BETWEEN_UPDATES, PARALLEL_UPDATES, SCAN_INTERVAL, - STARTUP_MESSAGE, SENSOR_COLLECTORS_AFVALWIJZER, SENSOR_COLLECTORS_XIMMIO, + STARTUP_MESSAGE, ) -from .collector.mijnafvalwijzer import MijnAfvalWijzerCollector -from .collector.ximmio import XimmioCollector - from .sensor_custom import CustomSensor from .sensor_provider import ProviderSensor -from functools import partial - -from homeassistant.components.sensor import PLATFORM_SCHEMA -import homeassistant.helpers.config_validation as cv -from homeassistant.util import Throttle -import voluptuous as vol - PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( { - vol.Optional(CONF_COLLECTOR.strip().lower(), default="mijnafvalwijzer"): cv.string, + vol.Optional( + CONF_COLLECTOR.strip().lower(), default="mijnafvalwijzer" + ): cv.string, vol.Required(CONF_POSTAL_CODE.strip(), default="1234AB"): cv.string, vol.Required(CONF_STREET_NUMBER.strip(), default="5"): cv.string, vol.Optional(CONF_SUFFIX.strip(), default=""): cv.string, @@ -135,11 +136,23 @@ def update(self): try: if provider in SENSOR_COLLECTORS_AFVALWIJZER: collector = MijnAfvalWijzerCollector( - provider, postal_code, street_number, suffix, exclude_pickup_today, exclude_list, default_label + provider, + postal_code, + street_number, + suffix, + exclude_pickup_today, + exclude_list, + default_label, ) elif provider in SENSOR_COLLECTORS_XIMMIO.keys(): collector = XimmioCollector( - provider, postal_code, street_number, suffix, exclude_pickup_today, exclude_list, default_label + provider, + postal_code, + street_number, + suffix, + exclude_pickup_today, + exclude_list, + default_label, ) except ValueError as err: _LOGGER.error("Check afvalwijzer platform settings %s", err.args) diff --git a/custom_components/afvalwijzer/sensor_custom.py b/custom_components/afvalwijzer/sensor_custom.py index d27be96..3a866fa 100755 --- a/custom_components/afvalwijzer/sensor_custom.py +++ b/custom_components/afvalwijzer/sensor_custom.py @@ -2,7 +2,11 @@ from datetime import datetime import hashlib +from homeassistant.helpers.entity import Entity +from homeassistant.util import Throttle + from .const.const import ( + _LOGGER, ATTR_LAST_UPDATE, ATTR_YEAR_MONTH_DAY_DATE, CONF_DEFAULT_LABEL, @@ -14,12 +18,8 @@ PARALLEL_UPDATES, SENSOR_ICON, SENSOR_PREFIX, - _LOGGER, ) -from homeassistant.helpers.entity import Entity -from homeassistant.util import Throttle - class CustomSensor(Entity): def __init__(self, hass, waste_type, fetch_data, config): @@ -30,7 +30,11 @@ def __init__(self, hass, waste_type, fetch_data, config): self._id_name = self.config.get(CONF_ID) self._default_label = self.config.get(CONF_DEFAULT_LABEL) self._last_update = None - self._name = SENSOR_PREFIX + (self._id_name + " " if len(self._id_name) > 0 else "") + self.waste_type + self._name = ( + SENSOR_PREFIX + + (self._id_name + " " if len(self._id_name) > 0 else "") + + self.waste_type + ) self._state = self.config.get(CONF_DEFAULT_LABEL) self._icon = SENSOR_ICON self._year_month_day_date = None @@ -89,7 +93,9 @@ async def async_update(self): self._year_month_day_date = str(collection_date_us) # Add the NL date format as default state - self._state = datetime.strftime(waste_data_custom[self.waste_type].date(), "%d-%m-%Y") + self._state = datetime.strftime( + waste_data_custom[self.waste_type].date(), "%d-%m-%Y" + ) else: _LOGGER.debug( "Generating state via AfvalwijzerCustomSensor for = %s with value %s", diff --git a/custom_components/afvalwijzer/sensor_provider.py b/custom_components/afvalwijzer/sensor_provider.py index eda323d..da29431 100755 --- a/custom_components/afvalwijzer/sensor_provider.py +++ b/custom_components/afvalwijzer/sensor_provider.py @@ -2,7 +2,11 @@ from datetime import date, datetime, timedelta import hashlib +from homeassistant.helpers.entity import Entity +from homeassistant.util import Throttle + from .const.const import ( + _LOGGER, ATTR_DAYS_UNTIL_COLLECTION_DATE, ATTR_IS_COLLECTION_DATE_DAY_AFTER_TOMORROW, ATTR_IS_COLLECTION_DATE_TODAY, @@ -10,8 +14,8 @@ ATTR_LAST_UPDATE, ATTR_YEAR_MONTH_DAY_DATE, CONF_DEFAULT_LABEL, - CONF_ID, CONF_EXCLUDE_PICKUP_TODAY, + CONF_ID, CONF_POSTAL_CODE, CONF_STREET_NUMBER, CONF_SUFFIX, @@ -19,12 +23,8 @@ PARALLEL_UPDATES, SENSOR_ICON, SENSOR_PREFIX, - _LOGGER, ) -from homeassistant.helpers.entity import Entity -from homeassistant.util import Throttle - class ProviderSensor(Entity): def __init__(self, hass, waste_type, fetch_data, config): @@ -35,7 +35,11 @@ def __init__(self, hass, waste_type, fetch_data, config): self._id_name = self.config.get(CONF_ID) self._default_label = self.config.get(CONF_DEFAULT_LABEL) self._exclude_pickup_today = self.config.get(CONF_EXCLUDE_PICKUP_TODAY) - self._name = SENSOR_PREFIX + (self._id_name + " " if len(self._id_name) > 0 else "") + self.waste_type + self._name = ( + SENSOR_PREFIX + + (self._id_name + " " if len(self._id_name) > 0 else "") + + self.waste_type + ) self._icon = SENSOR_ICON self._state = self.config.get(CONF_DEFAULT_LABEL) self._last_update = None @@ -107,14 +111,20 @@ async def async_update(self): self._days_until_collection_date = delta.days # Check if the collection days are in today, tomorrow and/or the day after tomorrow - self._is_collection_date_today = date.today() == collection_date_us - self._is_collection_date_tomorrow = date.today() + timedelta(days=1) == collection_date_us + self._is_collection_date_today = ( + date.today() == collection_date_us + ) + self._is_collection_date_tomorrow = ( + date.today() + timedelta(days=1) == collection_date_us + ) self._is_collection_date_day_after_tomorrow = ( date.today() + timedelta(days=2) == collection_date_us ) # Add the NL date format as default state - self._state = datetime.strftime(waste_data_provider[self.waste_type].date(), "%d-%m-%Y") + self._state = datetime.strftime( + waste_data_provider[self.waste_type].date(), "%d-%m-%Y" + ) else: _LOGGER.debug( "Generating state via AfvalwijzerCustomSensor for = %s with value %s", diff --git a/custom_components/afvalwijzer/test/test_module.py b/custom_components/afvalwijzer/test/test_module.py index 2e002e4..bd2845b 100644 --- a/custom_components/afvalwijzer/test/test_module.py +++ b/custom_components/afvalwijzer/test/test_module.py @@ -13,10 +13,7 @@ from ..collector.mijnafvalwijzer import MijnAfvalWijzerCollector from ..collector.ximmio import XimmioCollector -from ..const.const import ( - SENSOR_COLLECTORS_AFVALWIJZER, - SENSOR_COLLECTORS_XIMMIO, -) +from ..const.const import SENSOR_COLLECTORS_AFVALWIJZER, SENSOR_COLLECTORS_XIMMIO # provider = "afvalstoffendienstkalender" # api_token = "5ef443e778f41c4f75c69459eea6e6ae0c2d92de729aa0fc61653815fbd6a8ca" @@ -42,9 +39,25 @@ # street_number = "38" if provider in SENSOR_COLLECTORS_AFVALWIJZER: - collector = MijnAfvalWijzerCollector(provider, postal_code, street_number, suffix, exclude_pickup_today, exclude_list, default_label) + collector = MijnAfvalWijzerCollector( + provider, + postal_code, + street_number, + suffix, + exclude_pickup_today, + exclude_list, + default_label, + ) elif provider in SENSOR_COLLECTORS_XIMMIO.keys(): - collector = XimmioCollector(provider, postal_code, street_number, suffix, exclude_pickup_today, exclude_list, default_label) + collector = XimmioCollector( + provider, + postal_code, + street_number, + suffix, + exclude_pickup_today, + exclude_list, + default_label, + ) # data = XimmioCollector().get_waste_data_provider("meerlanden", postal_code2, street_number2, suffix, default_label, exclude_list)