Skip to content

Commit

Permalink
fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
Bram van Dartel committed Dec 28, 2024
1 parent 4b8577e commit ad113d4
Show file tree
Hide file tree
Showing 9 changed files with 364 additions and 139 deletions.
46 changes: 23 additions & 23 deletions custom_components/afvalwijzer/__init__.py
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.typing import ConfigType
from .const.const import DOMAIN
# from homeassistant.config_entries import ConfigEntry
# from homeassistant.core import HomeAssistant
# from homeassistant.helpers.typing import ConfigType
# from .const.const import DOMAIN


async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Set up the Afvalwijzer integration."""
hass.data.setdefault(DOMAIN, {})
return True
# async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
# """Set up the Afvalwijzer integration."""
# hass.data.setdefault(DOMAIN, {})
# return True


async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up Afvalwijzer from a config entry."""
# Store config entry data
hass.data[DOMAIN][entry.entry_id] = entry.data
# async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
# """Set up Afvalwijzer from a config entry."""
# # Store config entry data
# hass.data[DOMAIN][entry.entry_id] = entry.data

# Forward the setup to the sensor platform
await hass.config_entries.async_forward_entry_setups(entry, ["sensor"])
return True
# # Forward the setup to the sensor platform
# await hass.config_entries.async_forward_entry_setups(entry, ["sensor"])
# return True


async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload a config entry."""
# Remove stored data
if entry.entry_id in hass.data[DOMAIN]:
hass.data[DOMAIN].pop(entry.entry_id)
# async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
# """Unload a config entry."""
# # Remove stored data
# if entry.entry_id in hass.data[DOMAIN]:
# hass.data[DOMAIN].pop(entry.entry_id)

# Unload the sensor platform
await hass.config_entries.async_forward_entry_unload(entry, "sensor")
return True
# # Unload the sensor platform
# await hass.config_entries.async_forward_entry_unload(entry, "sensor")
# return True
116 changes: 63 additions & 53 deletions custom_components/afvalwijzer/collector/klikogroep.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,88 +5,98 @@
from urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)


def get_waste_data_raw(provider, username, password):
url = SENSOR_COLLECTORS_KLIKOGROEP[provider]['url']
app = SENSOR_COLLECTORS_KLIKOGROEP[provider]['app']
"""Fetch raw waste collection data from the provider API."""
try:
base_url = SENSOR_COLLECTORS_KLIKOGROEP[provider]['url']
app = SENSOR_COLLECTORS_KLIKOGROEP[provider]['app']

headers = {
'Content-Type': 'application/json',
'Referer': url,
}
headers = {
'Content-Type': 'application/json',
'Referer': base_url,
}

# Login and get token
token = _login_and_get_token(base_url, headers, provider, username, password, app)

# Get waste calendar
waste_data_raw = _fetch_waste_calendar(base_url, headers, token, provider, app)

# Logout (optional, no error handling required here)
_logout(base_url, headers, token, provider, app)

return waste_data_raw
except KeyError as err:
raise ValueError(f"Invalid provider configuration: {err}") from err

##########################################################################
# First request: login and get token
##########################################################################
def _login_and_get_token(base_url, headers, provider, username, password, app):
"""Authenticate and retrieve a session token."""
login_url = f"{base_url}/loginWithPassword"
data = {
"cardNumber": username,
"password": password,
"clientName": provider,
"app": app,
}

try:
raw_response = requests.post(url="{}/loginWithPassword".format(url), timeout=60, headers=headers, json=data)
raw_response.raise_for_status()
response = requests.post(url=login_url, timeout=60, headers=headers, json=data)
response.raise_for_status()
response_data = response.json()
if not response_data.get('success'):
raise ValueError('Login failed. Check username and/or password!')
return response_data["token"]
except requests.exceptions.RequestException as err:
raise ValueError(err) from err

try:
response = raw_response.json()
raise ValueError(f"Login request failed: {err}") from err
except ValueError as err:
raise ValueError(f"Invalid and/or no data received from {url}/loginWithPassword") from err
raise ValueError(f"Invalid response from {login_url}: {err}") from err

if 'success' not in response or not response['success']:
_LOGGER.error('Login failed. Check card number (username) and / or password!')
return

token = response["token"]

##########################################################################
# Second request: get the dates
##########################################################################
def _fetch_waste_calendar(base_url, headers, token, provider, app):
"""Retrieve the waste collection calendar."""
calendar_url = f"{base_url}/getMyWasteCalendar"
data = {
"token": token,
"clientName": provider,
"app": app,
}

try:
raw_response = requests.post(url="{}/getMyWasteCalendar".format(url), timeout=60, headers=headers, json=data)
raw_response.raise_for_status()
response = requests.post(url=calendar_url, timeout=60, headers=headers, json=data)
response.raise_for_status()
response_data = response.json()
except requests.exceptions.RequestException as err:
raise ValueError(err) from err

try:
response = raw_response.json()
raise ValueError(f"Waste calendar request failed: {err}") from err
except ValueError as err:
raise ValueError(f"Invalid and/or no data received from {url}/getMyWasteCalendar") from err
raise ValueError(f"Invalid response from {calendar_url}: {err}") from err

waste_data_raw = []
waste_type_mapping = {}
for waste_type in response['fractions']:
waste_type_mapping[waste_type['id']] = _waste_type_rename(waste_type['name'].lower())
return _parse_waste_calendar(response_data)

for pickup_date in response["dates"]:
num_pickup = len(response["dates"][pickup_date][0])
for idx in range(0, num_pickup):
pick_up = response["dates"][pickup_date][0][idx]
if pick_up != 0:
def _parse_waste_calendar(response):
"""Parse the waste calendar response into a structured list."""
waste_type_mapping = {
fraction['id']: _waste_type_rename(fraction['name'].lower())
for fraction in response.get('fractions', [])
}

waste_data_raw = []
for pickup_date, pickups in response.get("dates", {}).items():
for pick_up in pickups[0]:
if pick_up:
waste_data_raw.append({
"type": waste_type_mapping[pick_up],
"type": waste_type_mapping.get(pick_up, "unknown"),
"date": pickup_date,
})

##########################################################################
# Third request: invalidate token / close session
##########################################################################
return waste_data_raw

def _logout(base_url, headers, token, provider, app):
"""Log out to invalidate the session token."""
logout_url = f"{base_url}/logout"
data = {
"token": token,
"clientName": provider,
"app": app,
}

response = requests.post(url="{}/logout".format(url), timeout=60, headers=headers, json=data).json()
# We really don't care about this result, honestly.

return waste_data_raw
try:
requests.post(url=logout_url, timeout=60, headers=headers, json=data)
except requests.exceptions.RequestException:
# Logout failures are non-critical, so we can safely ignore them.
pass
4 changes: 4 additions & 0 deletions custom_components/afvalwijzer/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ async def async_step_user(self, user_input=None):
errors = {}

if user_input is not None:
# Ensure CONF_* is saved lowercase
user_input[CONF_COLLECTOR] = user_input.get(CONF_COLLECTOR, "").lower()
user_input[CONF_EXCLUDE_LIST] = user_input.get(CONF_EXCLUDE_LIST, "").lower()

# Perform validation
if not self._validate_postal_code(user_input.get(CONF_POSTAL_CODE)):
errors["postal_code"] = "config.error.invalid_postal_code"
Expand Down
59 changes: 0 additions & 59 deletions custom_components/afvalwijzer/tests/config_flow.py

This file was deleted.

Loading

0 comments on commit ad113d4

Please sign in to comment.