From a651ec72de0f8f36eba6e6f71fe355f87d777019 Mon Sep 17 00:00:00 2001
From: "th.l" <thl-cmk@outlook.com>
Date: Thu, 25 Jan 2024 20:22:05 +0100
Subject: [PATCH] update project

---
 README.md                                     |   2 +-
 mkp/fritzbox_smarthome-0.8.17-20240125.mkp    | Bin 0 -> 23033 bytes
 .../agent_based/fritzbox_smarthome_battery.py |  11 +
 .../agent_based/fritzbox_smarthome_button.py  | 103 +++++
 .../fritzbox_smarthome_humidity.py            |  79 ++++
 .../fritzbox_smarthome_power_meter.py         |  91 ++--
 .../fritzbox_smarthome_temperature.py         |  17 +-
 .../fritzbox_smarthome_thermostat.py          |  72 ++-
 .../agent_based/utils/fritzbox_smarthome.py   | 181 ++++++--
 source/checks/agent_fritzbox_smarthome        |   6 +-
 source/gui/dashboard/avm                      | 327 ++++++++++++++
 source/gui/metrics/fritzbox_smarthome.py      |  59 ++-
 source/gui/views/avm_fritzbox                 |  59 +++
 .../gui/views/avm_smart_home_devices_metrics  |  62 +++
 .../gui/views/avm_smart_home_devices_status   |  63 +++
 .../gui/views/invavmsmarthomedevices_filtered |  69 +++
 .../check_parameters/fritzbox_smarthome.py    |  17 +
 .../agent_fritzbox_smarthome.py               | 412 +++++++++++-------
 source/packages/fritzbox_smarthome            |  25 +-
 .../web/plugins/views/fritzbox_smarthome.py   |   2 +-
 .../plugins/wato/agent_fritzbox_smarthome.py  |   7 +
 21 files changed, 1377 insertions(+), 287 deletions(-)
 create mode 100644 mkp/fritzbox_smarthome-0.8.17-20240125.mkp
 create mode 100644 source/agent_based/fritzbox_smarthome_button.py
 create mode 100644 source/agent_based/fritzbox_smarthome_humidity.py
 create mode 100644 source/gui/dashboard/avm
 create mode 100644 source/gui/views/avm_fritzbox
 create mode 100644 source/gui/views/avm_smart_home_devices_metrics
 create mode 100644 source/gui/views/avm_smart_home_devices_status
 create mode 100644 source/gui/views/invavmsmarthomedevices_filtered

diff --git a/README.md b/README.md
index ef1f715..2217179 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-[PACKAGE]: ../../raw/master/mkp/fritzbox_smarthome-0.8.8-20240109.mkp "fritzbox_smarthome-0.8.8-20240109.mkp"
+[PACKAGE]: ../../raw/master/mkp/fritzbox_smarthome-0.8.17-20240125.mkp "fritzbox_smarthome-0.8.17-20240125.mkp"
 # AVM Fritz!Box Smarthome
 
 This repository contains a additional check_MK Fritz!Box Agent which can gather informations over the AVM AHA HTTP Interface about SmartHome Devices connected to an Fritz!Box. 
diff --git a/mkp/fritzbox_smarthome-0.8.17-20240125.mkp b/mkp/fritzbox_smarthome-0.8.17-20240125.mkp
new file mode 100644
index 0000000000000000000000000000000000000000..e6199e134be455277941021d53230cb8c9ebcae6
GIT binary patch
literal 23033
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

literal 0
HcmV?d00001

diff --git a/source/agent_based/fritzbox_smarthome_battery.py b/source/agent_based/fritzbox_smarthome_battery.py
index 57f3556..e9c8b75 100644
--- a/source/agent_based/fritzbox_smarthome_battery.py
+++ b/source/agent_based/fritzbox_smarthome_battery.py
@@ -13,10 +13,12 @@
 from typing import Dict
 
 from cmk.base.plugins.agent_based.agent_based_api.v1 import (
+    check_levels,
     Result,
     Service,
     State,
     register,
+    render,
 )
 from cmk.base.plugins.agent_based.agent_based_api.v1.type_defs import CheckResult, DiscoveryResult
 from cmk.base.plugins.agent_based.utils.fritzbox_smarthome import AvmSmartHomeDevice
@@ -56,6 +58,15 @@ def check_fritzbox_smarthome_battery_single(
     else:
         yield Result(state=State(params.get('battery_low', 2)), summary=_message)
 
+    if section.battery is not None:
+        yield from check_levels(
+            value=section.battery,
+            label='Battery',
+            metric_name='battery',
+            render_func=render.percent,
+            levels_lower=params.get('levels_lower'),
+        )
+
 
 def check_fritzbox_smarthome_battery_multiple(
         item, params, section: AvmSmartHomeDevice | Dict[str, AvmSmartHomeDevice]
diff --git a/source/agent_based/fritzbox_smarthome_button.py b/source/agent_based/fritzbox_smarthome_button.py
new file mode 100644
index 0000000..424d950
--- /dev/null
+++ b/source/agent_based/fritzbox_smarthome_button.py
@@ -0,0 +1,103 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# License: GNU General Public License v2
+#
+# Author: thl-cmk[at]outlook[dot]com
+# URL   : https://thl-cmk.hopto.org
+# Date  : 2024-01-10
+# File  : fritzbox_smarthome_button.py (check plugin)
+#
+#
+
+from time import localtime, strftime
+from typing import Dict
+
+from cmk.base.plugins.agent_based.agent_based_api.v1 import (
+    Service,
+    register,
+    Result,
+    State,
+)
+from cmk.base.plugins.agent_based.agent_based_api.v1.type_defs import CheckResult, DiscoveryResult
+from cmk.base.plugins.agent_based.utils.fritzbox_smarthome import AvmSmartHomeDevice, AvmButton, AVM_TIME_FORMAT
+
+
+def discovery_fritzbox_smarthome_button_single(
+        section: AvmSmartHomeDevice | Dict[str, AvmSmartHomeDevice]
+) -> DiscoveryResult:
+    if isinstance(section, AvmSmartHomeDevice):
+        if isinstance(section.buttons, list):
+            for button in section.buttons:
+                item = button.name.split(':')[-1].strip()  # name="Button01: Top right"
+                yield Service(item=item, parameters={'discovered_id': button.id})
+
+
+def discovery_fritzbox_smarthome_button_multiple(
+        section: AvmSmartHomeDevice | Dict[str, AvmSmartHomeDevice]
+) -> DiscoveryResult:
+    if not isinstance(section, AvmSmartHomeDevice):
+        for device_id, device in section.items():
+            if isinstance(device.buttons, list):
+                for button in device.buttons:
+                    item = button.name.split(':')[-1].strip()  # name="Button01: Top right"
+                    yield Service(item=f'{device_id} {item}', parameters={'discovered_id': button.id})
+
+
+def check_fritzbox_smarthome_button_single(
+        item, params, section: AvmSmartHomeDevice | Dict[str, AvmSmartHomeDevice]
+) -> CheckResult:
+    if not isinstance(section, AvmSmartHomeDevice) or section.buttons is None:
+        return
+
+    button_found = None
+    for button in section.buttons:
+        if button.id == params['discovered_id']:
+            button_found: AvmButton | None = button
+            break
+
+    if not button_found:
+        return
+
+    if button_found.last_pressed_time_stamp is not None:
+        yield Result(
+            state=State.OK,
+            summary=f'Last pressed: {strftime(AVM_TIME_FORMAT, localtime(button_found.last_pressed_time_stamp))}'
+        )
+    else:
+        yield Result(state=State.OK, summary='Button never pressed')
+
+    yield Result(state=State.OK, notice=f'ID: {button_found.id}')
+    yield Result(state=State.OK, notice=f'Identifier: {button_found.identifier}')
+
+
+def check_fritzbox_smarthome_button_multiple(
+        item, params, section: AvmSmartHomeDevice | Dict[str, AvmSmartHomeDevice]
+) -> CheckResult:
+    if isinstance(section, Dict):
+        try:
+            yield from check_fritzbox_smarthome_button_single(item, params, section[item])
+        except KeyError:
+            return
+
+
+register.check_plugin(
+    name='fritzbox_smarthome_button_single',
+    service_name='Button %s',
+    sections=['fritzbox_smarthome'],
+    discovery_function=discovery_fritzbox_smarthome_button_single,
+    check_function=check_fritzbox_smarthome_button_single,
+    # check_ruleset_name='fritzbox_smarthome_button_single',
+    check_default_parameters={}
+)
+
+
+register.check_plugin(
+    name='fritzbox_smarthome_button_multiple',
+    service_name='Smarthome Button %s',
+    sections=['fritzbox_smarthome'],
+    discovery_function=discovery_fritzbox_smarthome_button_multiple,
+    check_function=check_fritzbox_smarthome_button_multiple,
+    # check_ruleset_name='fritzbox_smarthome_button_multiple',
+    check_default_parameters={}
+)
diff --git a/source/agent_based/fritzbox_smarthome_humidity.py b/source/agent_based/fritzbox_smarthome_humidity.py
new file mode 100644
index 0000000..caca820
--- /dev/null
+++ b/source/agent_based/fritzbox_smarthome_humidity.py
@@ -0,0 +1,79 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# License: GNU General Public License v2
+#
+# Author: thl-cmk[at]outlook[dot]com
+# URL   : https://thl-cmk.hopto.org
+# Date  : 2024-01-10
+# File  : fritzbox_smarthome_humidity.py (check plugin)
+#
+#
+
+from typing import Dict
+
+from cmk.base.plugins.agent_based.agent_based_api.v1 import Result, Service, State, register
+from cmk.base.plugins.agent_based.agent_based_api.v1.type_defs import CheckResult, DiscoveryResult
+from cmk.base.plugins.agent_based.utils.humidity import check_humidity
+from cmk.base.plugins.agent_based.utils.fritzbox_smarthome import AvmSmartHomeDevice
+
+
+def discovery_fritzbox_smarthome_humidity_single(
+        section: AvmSmartHomeDevice | Dict[str, AvmSmartHomeDevice]
+) -> DiscoveryResult:
+    if isinstance(section, AvmSmartHomeDevice):
+        if section.humidity:
+            yield Service()
+
+
+def discovery_fritzbox_smarthome_humidity_multiple(
+        section: AvmSmartHomeDevice | Dict[str, AvmSmartHomeDevice]
+) -> DiscoveryResult:
+    if not isinstance(section, AvmSmartHomeDevice):
+        for device_id, device in section.items():
+            if device.humidity:
+                yield Service(item=str(device_id))
+
+
+def check_fritzbox_smarthome_humidity_single(
+        params, section: AvmSmartHomeDevice | Dict[str, AvmSmartHomeDevice]
+) -> CheckResult:
+    if not isinstance(section, AvmSmartHomeDevice) or not section.humidity:
+        return
+    print(params)
+    if section.humidity.rel_humidity:
+        yield from check_humidity(
+            humidity=section.humidity.rel_humidity,
+            params=params.get('auto-migration-wrapper-key'),
+        )
+
+
+def check_fritzbox_smarthome_humidity_multiple(
+        item, params, section: AvmSmartHomeDevice | Dict[str, AvmSmartHomeDevice]
+) -> CheckResult:
+    if isinstance(section, Dict):
+        try:
+            yield from check_fritzbox_smarthome_humidity_single(params, section[item])
+        except KeyError:
+            return
+
+
+register.check_plugin(
+    name='fritzbox_smarthome_humidity_single',
+    service_name='Humidity',
+    sections=['fritzbox_smarthome'],
+    discovery_function=discovery_fritzbox_smarthome_humidity_single,
+    check_function=check_fritzbox_smarthome_humidity_single,
+    check_ruleset_name='single_humidity',
+    check_default_parameters={}
+)
+
+register.check_plugin(
+    name='fritzbox_smarthome_humidity',
+    service_name='Smarthome Humidity %s',
+    sections=['fritzbox_smarthome'],
+    discovery_function=discovery_fritzbox_smarthome_humidity_multiple,
+    check_function=check_fritzbox_smarthome_humidity_multiple,
+    check_ruleset_name='humidity',
+    check_default_parameters={}
+)
diff --git a/source/agent_based/fritzbox_smarthome_power_meter.py b/source/agent_based/fritzbox_smarthome_power_meter.py
index d966c89..74a8773 100644
--- a/source/agent_based/fritzbox_smarthome_power_meter.py
+++ b/source/agent_based/fritzbox_smarthome_power_meter.py
@@ -173,18 +173,21 @@ def discovery_fritzbox_smarthome_energy_multiple(
 
 
 def _cost_period_x(
-        value_store: FritzBoxValueStore,
-        period_name: str,
+        cost_kwh: float,
         current_period: int,
-        rate_name: str,
-        metric_name: str,
         last_reading: float,
-        precision: int,
         message: str,
-        cost_kwh: float,
+        metric_name: str,
+        period_name: str,
+        precision: int,
+        rate_name: str,
+        unit: str,
+        value_store: FritzBoxValueStore,
+        hours: float,
+        power: float
 ) -> CheckResult:
     # reset all
-    # value_store[rate_name] = 0
+    # value_store.set(rate_name) = 0
 
     if stored_period := value_store.get(key=period_name):
         value_store.set(key=period_name, value=current_period)
@@ -199,12 +202,15 @@ def _cost_period_x(
         value_store.set(key=rate_name, value=cost)
 
     cost = round(cost, precision)
-
-    yield Result(
-        state=State.OK,
-        notice=message.replace('__value__', f'{cost:.4f}')
+    cost_estimated = round((power / 1000 * cost_kwh * hours), 2)
+
+    yield from check_levels(
+        value=cost,
+        label=f'{message} (estimated per {message}: {cost_estimated})',
+        metric_name=metric_name,
+        notice_only=True,
+        render_func=lambda x: f'{x:.4f}{unit}'
     )
-    yield Metric(name=metric_name, value=cost)
 
 
 def check_fritzbox_smarthome_energy_single(
@@ -270,48 +276,60 @@ def check_fritzbox_smarthome_energy_single(
                 yield Result(state=State.OK, notice='Cost for this:')
                 loca_time = localtime()
                 yield from _cost_period_x(
-                    value_store=value_store,
-                    period_name='current_hour',
+                    cost_kwh=cost_kwh,
                     current_period=loca_time.tm_hour,
-                    rate_name='cost_this_hour',  # don't reuse -> cost_per_hour
-                    metric_name='cost_per_hour',
                     last_reading=energy,
+                    message=f'Hour',
+                    metric_name='cost_per_hour',
+                    period_name='current_hour',
                     precision=6,
-                    message=f'Hour_: __value__{unit_sign}',
-                    cost_kwh=cost_kwh,
+                    rate_name='cost_this_hour',  # don't reuse -> cost_per_hour
+                    unit=unit_sign,
+                    value_store=value_store,
+                    hours=1,
+                    power=section.power_meter.power,
                 )
                 yield from _cost_period_x(
-                    value_store=value_store,
-                    period_name='current_day',
+                    cost_kwh=cost_kwh,
                     current_period=loca_time.tm_mday,
-                    rate_name='cost_this_day',  # don't reuse -> cost_per_day
-                    metric_name='cost_per_day',
                     last_reading=energy,
+                    message=f'Day',
+                    metric_name='cost_per_day',
+                    period_name='current_day',
                     precision=4,
-                    message=f'Day__: __value__{unit_sign}',
-                    cost_kwh=cost_kwh,
+                    rate_name='cost_this_day',  # don't reuse -> cost_per_day
+                    unit=unit_sign,
+                    value_store=value_store,
+                    hours=24,
+                    power=section.power_meter.power,
                 )
                 yield from _cost_period_x(
-                    value_store=value_store,
-                    period_name='current_month',
+                    cost_kwh=cost_kwh,
                     current_period=loca_time.tm_mon,
-                    rate_name='cost_this_month',  # don't reuse -> cost_per_month
-                    metric_name='cost_per_month',
                     last_reading=energy,
+                    message=f'Month',
+                    metric_name='cost_per_month',
+                    period_name='current_month',
                     precision=4,
-                    message=f'Month: __value__{unit_sign}',
-                    cost_kwh=cost_kwh,
+                    rate_name='cost_this_month',  # don't reuse -> cost_per_month
+                    unit=unit_sign,
+                    value_store=value_store,
+                    hours=24 * 365 / 12,
+                    power=section.power_meter.power,
                 )
                 yield from _cost_period_x(
-                    value_store=value_store,
-                    period_name='current_year',
+                    cost_kwh=cost_kwh,
                     current_period=loca_time.tm_year,
-                    rate_name='cost_this_year',  # don't reuse -> cost_per_year
-                    metric_name='cost_per_year',
                     last_reading=energy,
+                    message=f'Year',
+                    metric_name='cost_per_year',
+                    period_name='current_year',
                     precision=4,
-                    message=f'Year_: __value__{unit_sign}',
-                    cost_kwh=cost_kwh,
+                    rate_name='cost_this_year',  # don't reuse -> cost_per_year
+                    unit=unit_sign,
+                    value_store=value_store,
+                    hours=24 * 365,
+                    power=section.power_meter.power,
                 )
                 yield Result(state=State.OK, notice=' ')
 
@@ -355,3 +373,4 @@ register.check_plugin(
     check_ruleset_name='energy_multiple',
     check_default_parameters={}
 )
+
diff --git a/source/agent_based/fritzbox_smarthome_temperature.py b/source/agent_based/fritzbox_smarthome_temperature.py
index 86ebd47..ac79231 100644
--- a/source/agent_based/fritzbox_smarthome_temperature.py
+++ b/source/agent_based/fritzbox_smarthome_temperature.py
@@ -47,16 +47,19 @@ def check_fritzbox_smarthome_temperature_single(
             params=params,
         )
     if section.temperature.offset:
-        _status = section.temperature.celsius + section.temperature.offset * -1
-        _message = (
-            f'Temperature measured at the thermostat: '
-            f'{_render_temp_with_unit(_status, params.get("output_unit", "c"))}'
+        temp_sensor = section.temperature.celsius + section.temperature.offset * -1
+        _details = (
+            f'Temperature measured at the sensor'
+            f': {_render_temp_with_unit(temp_sensor, params.get("output_unit", "c"))}'
         )
-        yield Result(state=State.OK, notice=_message)
+        _summary = f'At the sensor: {_render_temp_with_unit(temp_sensor, params.get("output_unit", "c"))}'
+        yield Result(state=State.OK, summary=_summary, details=_details)
+
         yield Result(
             state=State.OK,
-            notice=f'Temperature offset: '
-                   f'{_render_temp_with_unit(section.temperature.offset, params.get("output_unit", "c"))}'
+            summary=f'Offset: {_render_temp_with_unit(section.temperature.offset, params.get("output_unit", "c"))}',
+            details=f'Temperature offset: '
+                    f'{_render_temp_with_unit(section.temperature.offset, params.get("output_unit", "c"))}'
         )
 
 
diff --git a/source/agent_based/fritzbox_smarthome_thermostat.py b/source/agent_based/fritzbox_smarthome_thermostat.py
index 9828c3c..ee9aa20 100644
--- a/source/agent_based/fritzbox_smarthome_thermostat.py
+++ b/source/agent_based/fritzbox_smarthome_thermostat.py
@@ -21,9 +21,7 @@ from cmk.base.plugins.agent_based.agent_based_api.v1 import (
     register,
 )
 from cmk.base.plugins.agent_based.agent_based_api.v1.type_defs import CheckResult, DiscoveryResult
-from cmk.base.plugins.agent_based.utils.fritzbox_smarthome import AvmSmartHomeDevice
-
-_TIME_FORMAT = '%Y-%m-%dT%H:%M:%S'
+from cmk.base.plugins.agent_based.utils.fritzbox_smarthome import AvmSmartHomeDevice, AVM_TIME_FORMAT
 
 
 def discovery_fritzbox_smarthome_thermostat_single(
@@ -68,6 +66,7 @@ def check_fritzbox_smarthome_thermostat_single(
         yield Result(state=State(params.get('state_off', 0)), summary=f'Temperature target: radiator off')
     else:
         deviation = thermostat.temp_current - thermostat.temp_target
+        yield Metric(name='temp_deviation', value=deviation)
         if deviation == 0:
             yield Result(state=State.OK, summary=f'Temperature current: {thermostat.temp_target}°C')
         else:
@@ -88,8 +87,8 @@ def check_fritzbox_smarthome_thermostat_single(
         )
         yield Metric(name='temp_target', value=thermostat.temp_target)
 
-    yield Result(state=State.OK, notice=f'Temperature economic: {thermostat.temp_economic}°C')
     yield Result(state=State.OK, notice=f'Temperature comfort: {thermostat.temp_comfort}°C')
+    yield Result(state=State.OK, notice=f'Temperature cool-down: {thermostat.temp_economic}°C')
 
     yield Metric(name='temp_current', value=thermostat.temp_current)
     yield Metric(name='temp_comfort', value=thermostat.temp_comfort)
@@ -98,7 +97,7 @@ def check_fritzbox_smarthome_thermostat_single(
     if thermostat.next_change:
         yield Result(
             state=State.OK,
-            notice=f'End of period: {strftime(_TIME_FORMAT, localtime(thermostat.next_change.end_period))}'
+            notice=f'End of period: {strftime(AVM_TIME_FORMAT, localtime(thermostat.next_change.end_period))}'
         )
         yield Result(
             state=State.OK,
@@ -114,6 +113,69 @@ def check_fritzbox_smarthome_thermostat_single(
             summary=f'Error Code: {thermostat.error_code} (see details)',
             details=_message)
 
+    _adaptive_heating_active = {
+        0: 'inactive',
+        1: 'activ'
+    }
+    if thermostat.adaptive_heating_active is not None:
+        yield Result(
+            state=State.OK,
+            notice=f'Adaptive heating: {_adaptive_heating_active.get(thermostat.adaptive_heating_active)}')
+
+        _adaptive_heating_running = {
+            0: 'not running',
+            1: 'running',
+        }
+        if thermostat.adaptive_heating_active == 1 and thermostat.adaptive_heating_running is not None:
+            yield Result(
+                state=State.OK,
+                notice=f'Adaptive heating: {_adaptive_heating_running.get(thermostat.adaptive_heating_running)}'
+            )
+
+    _boost_active = {
+        0: 'inactive',
+        1: 'active',
+    }
+    if thermostat.boost_active is not None:
+        _message = f'Boost mode: {_boost_active.get(thermostat.boost_active)}'
+        if not thermostat.boost_active:
+            yield Result(state=State.OK, notice=_message)
+        else:
+            yield Result(state=State(params.get('state_boost_mode', 1)), notice=_message)
+            if thermostat.boost_active_end_time is not None:
+                _end_time = strftime(AVM_TIME_FORMAT, localtime(thermostat.boost_active_end_time))
+                _message = f'Boost mode end: {_end_time}'
+                yield Result(state=State(params.get('state_boost_mode', 1)), notice=_message)
+
+    _holiday_active = {
+        0: 'inactive',
+        1: 'active',
+    }
+    if thermostat.holiday_active is not None:
+        yield Result(state=State.OK, notice=f'Holiday mode: {_holiday_active.get(thermostat.holiday_active)}')
+
+    _summer_active = {
+        0: 'inactive',
+        1: 'active',
+    }
+    if thermostat.summer_active is not None:
+        yield Result(state=State.OK, notice=f'Summer mode: {_summer_active.get(thermostat.summer_active)}')
+
+    _windows_open = {
+        0: 'inactive',
+        1: 'active',
+    }
+    if thermostat.window_open_activ is not None:
+        _message = f'Windows open mode: {_windows_open.get(thermostat.window_open_activ)}'
+        if not thermostat.window_open_activ:
+            yield Result(state=State.OK, notice=_message)
+        else:
+            yield Result(state=State(params.get('state_windows_open', 1)), notice=_message)
+            if thermostat.window_open_active_end_time is not None:
+                _end_time = strftime(AVM_TIME_FORMAT, localtime(thermostat.window_open_active_end_time))
+                _message = f'Window open mode end: {_end_time}'
+                yield Result(state=State(params.get('state_windows_open', 1)), notice=_message)
+
 
 def check_fritzbox_smarthome_thermostat_multiple(
         item, params, section: AvmSmartHomeDevice | Dict[str, AvmSmartHomeDevice]
diff --git a/source/agent_based/utils/fritzbox_smarthome.py b/source/agent_based/utils/fritzbox_smarthome.py
index b361852..9669cea 100644
--- a/source/agent_based/utils/fritzbox_smarthome.py
+++ b/source/agent_based/utils/fritzbox_smarthome.py
@@ -21,6 +21,19 @@ from json import loads, dumps
 from cmk.checkers import plugin_contexts
 
 
+@dataclass(frozen=True)
+class AvmButton:
+    identifier: str
+    id: str
+    name: str
+    last_pressed_time_stamp: int
+
+
+@dataclass(frozen=True)
+class AvmHumidity:
+    rel_humidity: int
+
+
 @dataclass(frozen=True)
 class AvmTemperature:
     celsius: float | None
@@ -52,15 +65,15 @@ class AvmThermostat:
     temp_current: float | None
     temp_economic: float | None
     temp_target: float | None
+    next_change: AvmNextChange | None = None
     adaptive_heating_active: int | None = None
     adaptive_heating_running: int | None = None
-    battery: float | None = None
     boost_active: int | None = None
     boost_active_end_time: int | None = None
     holiday_active: int | None = None
-    next_change: AvmNextChange | None = None
     summer_active: int | None = None
     window_open_activ: int | None = None
+    window_open_active_end_time: int | None = None
 
 
 @dataclass(frozen=True)
@@ -80,6 +93,7 @@ class AvmSmartHomeDevice:
     name: str
     present: int
     product_name: str
+    battery: int | None = None
     battery_low: int | None = None
     device_lock: int | None = None
     lock: int | None = None
@@ -89,17 +103,59 @@ class AvmSmartHomeDevice:
     temperature: AvmTemperature | None = None
     thermostat: AvmThermostat | None = None
     tx_busy: int | None = None
-
-
-_AVM_THERMOSTAT = 'hkr'
-_AVM_SWITCH = 'switch'
+    buttons: list[AvmButton] | None = None
+    humidity: AvmHumidity | None = None
+
+
+_AVM_ADAPTIVE_HEATING_ACTIVE = 'adaptiveHeatingActive'
+_AVM_ADAPTIVE_HEATING_RUNNING = 'adaptiveHeatingRunning'
+_AVM_BATTERY = 'battery'
+_AVM_BATTERY_LOW = 'batterylow'
+_AVM_BOOST_ACTIVE = 'boostactive'
+_AVM_BOOST_ACTIVE_END_TIME = 'boostactiveendtime'
+_AVM_CELSIUS = 'celsius'
+_AVM_DEVICE_LOCK = 'devicelock'
+_AVM_END_PERIOD = 'endperiod'
+_AVM_ENERGY = 'energy'
+_AVM_ERROR_CODE = 'errorcode'
+_AVM_FUNCTION_BIT_MASK = 'functionbitmask'
+_AVM_FW_REVISION = 'fwversion'
+_AVM_HOLIDAY_ACTIVE = 'holidayactive'
+_AVM_HUMIDITY = 'humidity'
+_AVM_ID = 'id'
+_AVM_IDENTIFIER = 'identifier'
+_AVM_LAST_PRESSED_TIME_STAMP = 'lastpressedtimestamp'
+_AVM_LOCK = 'lock'
+_AVM_MANUFACTURER = 'manufacturer'
+_AVM_MODE = 'mode'
+_AVM_NAME='name'
+_AVM_NEXT_CHANGE = 'nextchange'
+_AVM_OFFSET = 'offset'
+_AVM_POWER = 'power'
 _AVM_POWER_METER = 'powermeter'
-_AVM_TEMPERATURE = 'temperature'
+_AVM_PRESENT = 'present'
+_AVM_PRODUCT_NAME = 'productname'
+_AVM_REL_HUMIDITY = 'rel_humidity'
 _AVM_SIMPLE_ON_OFF = 'simpleonoff'
-_AVM_NEXT_CHANGE = 'nextchange'
+_AVM_STATE = 'state'
+_AVM_SUMMER_ACTIVE = 'summeractive'
+_AVM_SWITCH = 'switch'
+_AVM_TEMPERATURE = 'temperature'
+_AVM_TEMP_CHANGE = 'tchange'
+_AVM_TEMP_COMFORT = 'komfort'
+_AVM_TEMP_CURRENT = 'tist'
+_AVM_TEMP_ECONOMIC = 'absenk'
+_AVM_TEMP_TARGET = 'tsoll'
+_AVM_THERMOSTAT = 'hkr'
+_AVM_TX_BUSY = 'txbusy'
+_AVM_VOLTAGE = 'voltage'
+_AVM_WINDOW_OPEN_ACTIV = 'windowopenactiv'
+_AVM_WINDOW_OPEN_ACTIVE_END_TIME = 'windowopenactiveendtime'
 
 _OMD_ROOT = environ["OMD_ROOT"]
 
+AVM_TIME_FORMAT = '%Y-%m-%dT%H:%M:%S'
+
 
 class FritzBoxValueStore:
     """
@@ -150,91 +206,136 @@ class FritzBoxValueStore:
         self._file.write_text(dumps(self._counters))
 
 
+def _get_battery(device: Dict[str, Any]) -> int | None:
+    try:
+        return int(device[_AVM_THERMOSTAT][_AVM_BATTERY])
+    except (KeyError, ValueError):
+        pass
+
+    try:
+        return int(device[_AVM_BATTERY])
+    except (KeyError, ValueError):
+        pass
+
+
 def _get_battery_low(device: Dict[str, Any]) -> int | None:
     try:
-        return int(device[_AVM_THERMOSTAT]['batterylow'])
+        return int(device[_AVM_THERMOSTAT][_AVM_BATTERY_LOW])
+    except (KeyError, ValueError):
+        pass
+
+    try:
+        return int(device[_AVM_BATTERY_LOW])
     except (KeyError, ValueError):
         pass
 
 
 def _get_lock(device: Dict[str, Any]) -> int | None:
     try:
-        return int(device[_AVM_THERMOSTAT]['lock'])
+        return int(device[_AVM_THERMOSTAT][_AVM_LOCK])
     except (KeyError, ValueError):
         pass
 
     try:
-        return int(device[_AVM_SWITCH]['lock'])
+        return int(device[_AVM_SWITCH][_AVM_LOCK])
     except (KeyError, ValueError):
         pass
 
 
 def _get_device_lock(device: Dict[str, Any]) -> int | None:
     try:
-        return int(device[_AVM_THERMOSTAT]['devicelock'])
+        return int(device[_AVM_THERMOSTAT][_AVM_DEVICE_LOCK])
     except (KeyError, ValueError):
         pass
 
     try:
-        return int(device[_AVM_SWITCH]['devicelock'])
+        return int(device[_AVM_SWITCH][_AVM_DEVICE_LOCK])
     except (KeyError, ValueError):
         pass
 
 
+def _get_buttons(device: Dict[str, any]) -> List[AvmButton] | None:
+    return [
+        AvmButton(
+            identifier=device[key][_AVM_IDENTIFIER],
+            id=device[key][_AVM_ID],
+            name=device[key][_AVM_NAME],
+            last_pressed_time_stamp=_get_int(device[key][_AVM_LAST_PRESSED_TIME_STAMP])
+        ) for key in device.keys() if key.startswith('button')
+    ]
+
+
 def _get_int(value: str | None) -> int | None:
-    if value is not None and value.isdigit():
+    try:
         return int(value)
+    except (ValueError, TypeError):
+        return
 
 
 def _get_float(value: str | None, scale: float = 1.0) -> float | None:
-    if value is not None and value.isdigit():
+    try:
         return float(value) / scale
+    except (ValueError, TypeError):
+        return
 
 
 def parse_avm_smarthome_device(raw_device: Dict[str, Any]) -> AvmSmartHomeDevice:
     return AvmSmartHomeDevice(
+        battery=_get_battery(raw_device),
         battery_low=_get_battery_low(raw_device),
         device_lock=_get_device_lock(raw_device),
-        fbm=_get_int(raw_device.get('functionbitmask')),
-        functions=get_avm_device_functions_from_fbm(_get_int(raw_device.get('functionbitmask'))),
-        fw_version=str(raw_device['fwversion']),
-        id=str(raw_device['id']),
-        identifier=str(raw_device['identifier']),
+        fbm=_get_int(raw_device.get(_AVM_FUNCTION_BIT_MASK)),
+        functions=get_avm_device_functions_from_fbm(_get_int(raw_device.get(_AVM_FUNCTION_BIT_MASK))),
+        fw_version=str(raw_device[_AVM_FW_REVISION]),
+        id=str(raw_device[_AVM_ID]),
+        identifier=str(raw_device[_AVM_IDENTIFIER]),
         lock=_get_lock(raw_device),
-        manufacturer=str(raw_device['manufacturer']),
-        name=str(raw_device['name']),
-        present=_get_int(raw_device.get('present')),
-        product_name=str(raw_device['productname']),
-        tx_busy=_get_int(raw_device.get('txbusy')),
+        manufacturer=str(raw_device[_AVM_MANUFACTURER]),
+        name=str(raw_device[_AVM_NAME]),
+        present=_get_int(raw_device.get(_AVM_PRESENT)),
+        product_name=str(raw_device[_AVM_PRODUCT_NAME]),
+        tx_busy=_get_int(raw_device.get(_AVM_TX_BUSY)),
         temperature=AvmTemperature(
-                celsius=_get_float(value=raw_device[_AVM_TEMPERATURE].get('celsius'), scale=10.0),
-                offset=_get_float(value=raw_device[_AVM_TEMPERATURE].get('offset'), scale=10.0),
+                celsius=_get_float(value=raw_device[_AVM_TEMPERATURE].get(_AVM_CELSIUS), scale=10.0),
+                offset=_get_float(value=raw_device[_AVM_TEMPERATURE].get(_AVM_OFFSET), scale=10.0),
         ) if raw_device.get(_AVM_TEMPERATURE) else None,
         thermostat=AvmThermostat(
-            temp_current=_get_float(value=raw_device[_AVM_THERMOSTAT].get('tist'), scale=2.0),
-            temp_target=_get_float(value=raw_device[_AVM_THERMOSTAT].get('tsoll'), scale=2.0),
-            temp_economic=_get_float(value=raw_device[_AVM_THERMOSTAT].get('absenk'), scale=2.0),
-            temp_comfort=_get_float(value=raw_device[_AVM_THERMOSTAT].get('komfort'), scale=2.0),
-            error_code=_get_int(value=raw_device[_AVM_THERMOSTAT].get('errorcode')),
+            temp_current=_get_float(value=raw_device[_AVM_THERMOSTAT].get(_AVM_TEMP_CURRENT), scale=2.0),
+            temp_target=_get_float(value=raw_device[_AVM_THERMOSTAT].get(_AVM_TEMP_TARGET), scale=2.0),
+            temp_economic=_get_float(value=raw_device[_AVM_THERMOSTAT].get(_AVM_TEMP_ECONOMIC), scale=2.0),
+            temp_comfort=_get_float(value=raw_device[_AVM_THERMOSTAT].get(_AVM_TEMP_COMFORT), scale=2.0),
+            error_code=_get_int(value=raw_device[_AVM_THERMOSTAT].get(_AVM_ERROR_CODE)),
             next_change=AvmNextChange(
-                end_period=_get_int(raw_device[_AVM_THERMOSTAT][_AVM_NEXT_CHANGE].get('endperiod')),
+                end_period=_get_int(raw_device[_AVM_THERMOSTAT][_AVM_NEXT_CHANGE].get(_AVM_END_PERIOD)),
                 temp_change_to=_get_float(
-                    value=raw_device[_AVM_THERMOSTAT][_AVM_NEXT_CHANGE].get('tchange'), scale=2.0
+                    value=raw_device[_AVM_THERMOSTAT][_AVM_NEXT_CHANGE].get(_AVM_TEMP_CHANGE), scale=2.0
                 ),
             ) if raw_device[_AVM_THERMOSTAT].get(_AVM_NEXT_CHANGE) else None,
+            adaptive_heating_active=_get_int(value=raw_device[_AVM_THERMOSTAT].get(_AVM_ADAPTIVE_HEATING_ACTIVE)),
+            adaptive_heating_running=_get_int(value=raw_device[_AVM_THERMOSTAT].get(_AVM_ADAPTIVE_HEATING_RUNNING)),
+            boost_active=_get_int(value=raw_device[_AVM_THERMOSTAT].get(_AVM_BOOST_ACTIVE)),
+            boost_active_end_time=_get_int(value=raw_device[_AVM_THERMOSTAT].get(_AVM_BOOST_ACTIVE_END_TIME)),
+            holiday_active=_get_int(value=raw_device[_AVM_THERMOSTAT].get(_AVM_HOLIDAY_ACTIVE)),
+            summer_active=_get_int(value=raw_device[_AVM_THERMOSTAT].get(_AVM_SUMMER_ACTIVE)),
+            window_open_activ=_get_int(value=raw_device[_AVM_THERMOSTAT].get(_AVM_WINDOW_OPEN_ACTIV)),
+            window_open_active_end_time=_get_int(value=raw_device[_AVM_THERMOSTAT].get(_AVM_WINDOW_OPEN_ACTIVE_END_TIME)),
         ) if raw_device.get(_AVM_THERMOSTAT) else None,
         switch=AvmSwitch(
-            state=_get_int(raw_device[_AVM_SWITCH].get('state')),
-            mode=str(raw_device[_AVM_SWITCH]['mode']),
+            state=_get_int(raw_device[_AVM_SWITCH].get(_AVM_STATE)),
+            mode=str(raw_device[_AVM_SWITCH][_AVM_MODE]),
         ) if raw_device.get(_AVM_SWITCH) else None,
         power_meter=AvmPowerMeter(
-            voltage=_get_float(raw_device[_AVM_POWER_METER].get('voltage'),1000),
-            power=_get_float(raw_device[_AVM_POWER_METER].get('power'), 1000),
-            energy=_get_float(raw_device[_AVM_POWER_METER].get('energy')),  # / 1000,
+            voltage=_get_float(raw_device[_AVM_POWER_METER].get(_AVM_VOLTAGE),1000),
+            power=_get_float(raw_device[_AVM_POWER_METER].get(_AVM_POWER), 1000),
+            energy=_get_float(raw_device[_AVM_POWER_METER].get(_AVM_ENERGY)),  # / 1000,
         ) if raw_device.get(_AVM_POWER_METER) else None,
         simple_on_off=AvmSimpleOnOff(
-            state=_get_int(raw_device[_AVM_SIMPLE_ON_OFF].get('state')),
+            state=_get_int(raw_device[_AVM_SIMPLE_ON_OFF].get(_AVM_STATE)),
         ) if raw_device.get(_AVM_SIMPLE_ON_OFF) else None,
+        humidity=AvmHumidity(
+            rel_humidity=_get_int(raw_device[_AVM_HUMIDITY].get(_AVM_REL_HUMIDITY))
+        ) if raw_device.get(_AVM_HUMIDITY) else None,
+        buttons=_get_buttons(raw_device),
     )
 
 
diff --git a/source/checks/agent_fritzbox_smarthome b/source/checks/agent_fritzbox_smarthome
index 26a7854..33c8a5d 100644
--- a/source/checks/agent_fritzbox_smarthome
+++ b/source/checks/agent_fritzbox_smarthome
@@ -26,9 +26,6 @@ def agent_fritzbox_smarthome_arguments(params, hostname, ipaddress):
     if (ssl := params.get("ssl")) is not None:
         args.append("--ignore_ssl")
 
-    # if (piggyback := params.get("piggyback")) is not None:
-    #     args.append("--piggyback")
-
     if (prefix := params.get("prefix")) is not None:
         args.extend(["--prefix"] + [hostname])
 
@@ -38,6 +35,9 @@ def agent_fritzbox_smarthome_arguments(params, hostname, ipaddress):
     if (no_piggyback := params.get("no_piggyback")) is not None:
         args.append("--no-piggyback")
 
+    if (no_pbkdf2 := params.get("no_pbkdf2")) is not None:
+        args.append("--no-pbkdf2")
+
     return args
 
 
diff --git a/source/gui/dashboard/avm b/source/gui/dashboard/avm
new file mode 100644
index 0000000..c81a61a
--- /dev/null
+++ b/source/gui/dashboard/avm
@@ -0,0 +1,327 @@
+{'avm': {'add_context_to_title': False,
+         'context': {'host_labels': {'host_labels_1_bool': 'and',
+                                     'host_labels_1_vs_1_bool': 'and',
+                                     'host_labels_1_vs_1_vs': 'fritz/smarthome/device:yes',
+                                     'host_labels_1_vs_2_bool': 'or',
+                                     'host_labels_1_vs_2_vs': 'cmk/os_family:FRITZ!OS',
+                                     'host_labels_1_vs_3_bool': 'and',
+                                     'host_labels_1_vs_@:@_bool': 'and',
+                                     'host_labels_1_vs_count': '3',
+                                     'host_labels_1_vs_indexof_1': '1',
+                                     'host_labels_1_vs_indexof_2': '2',
+                                     'host_labels_1_vs_indexof_3': '3',
+                                     'host_labels_1_vs_indexof_@:@': '',
+                                     'host_labels_1_vs_orig_indexof_1': '1',
+                                     'host_labels_1_vs_orig_indexof_2': '2',
+                                     'host_labels_1_vs_orig_indexof_3': '3',
+                                     'host_labels_1_vs_orig_indexof_@:@': '',
+                                     'host_labels_@!@_bool': 'and',
+                                     'host_labels_@!@_vs_1_bool': 'and',
+                                     'host_labels_@!@_vs_@:@_bool': 'and',
+                                     'host_labels_@!@_vs_count': '1',
+                                     'host_labels_@!@_vs_indexof_1': '1',
+                                     'host_labels_@!@_vs_indexof_@:@': '',
+                                     'host_labels_@!@_vs_orig_indexof_1': '1',
+                                     'host_labels_@!@_vs_orig_indexof_@:@': '',
+                                     'host_labels_count': '1',
+                                     'host_labels_indexof_1': '1',
+                                     'host_labels_indexof_@!@': '',
+                                     'host_labels_orig_indexof_1': '1',
+                                     'host_labels_orig_indexof_@!@': ''}},
+         'dashlets': [{'background': True,
+                       'context': {'host_labels': {'host_labels_1_bool': 'and',
+                                                   'host_labels_1_vs_1_bool': 'and',
+                                                   'host_labels_1_vs_1_vs': 'cmk/os_family:FRITZ!OS',
+                                                   'host_labels_1_vs_2_bool': 'and',
+                                                   'host_labels_1_vs_@:@_bool': 'and',
+                                                   'host_labels_1_vs_count': '2',
+                                                   'host_labels_1_vs_indexof_1': '1',
+                                                   'host_labels_1_vs_indexof_2': '2',
+                                                   'host_labels_1_vs_indexof_@:@': '',
+                                                   'host_labels_1_vs_orig_indexof_1': '1',
+                                                   'host_labels_1_vs_orig_indexof_2': '2',
+                                                   'host_labels_1_vs_orig_indexof_@:@': '',
+                                                   'host_labels_@!@_bool': 'and',
+                                                   'host_labels_@!@_vs_1_bool': 'and',
+                                                   'host_labels_@!@_vs_@:@_bool': 'and',
+                                                   'host_labels_@!@_vs_count': '1',
+                                                   'host_labels_@!@_vs_indexof_1': '1',
+                                                   'host_labels_@!@_vs_indexof_@:@': '',
+                                                   'host_labels_@!@_vs_orig_indexof_1': '1',
+                                                   'host_labels_@!@_vs_orig_indexof_@:@': '',
+                                                   'host_labels_count': '1',
+                                                   'host_labels_indexof_1': '1',
+                                                   'host_labels_indexof_@!@': '',
+                                                   'host_labels_orig_indexof_1': '1',
+                                                   'host_labels_orig_indexof_@!@': ''}},
+                       'name': 'avm_fritzbox',
+                       'position': (1, 1),
+                       'show_title': True,
+                       'single_infos': [],
+                       'size': (0, 0),
+                       'type': 'linked_view'},
+                      {'background': True,
+                       'context': {'host_labels': {'host_labels_1_bool': 'and',
+                                                   'host_labels_1_vs_1_bool': 'and',
+                                                   'host_labels_1_vs_1_vs': 'fritz/smarthome/device:yes',
+                                                   'host_labels_1_vs_2_bool': 'and',
+                                                   'host_labels_1_vs_@:@_bool': 'and',
+                                                   'host_labels_1_vs_count': '2',
+                                                   'host_labels_1_vs_indexof_1': '1',
+                                                   'host_labels_1_vs_indexof_2': '2',
+                                                   'host_labels_1_vs_indexof_@:@': '',
+                                                   'host_labels_1_vs_orig_indexof_1': '1',
+                                                   'host_labels_1_vs_orig_indexof_2': '2',
+                                                   'host_labels_1_vs_orig_indexof_@:@': '',
+                                                   'host_labels_@!@_bool': 'and',
+                                                   'host_labels_@!@_vs_1_bool': 'and',
+                                                   'host_labels_@!@_vs_@:@_bool': 'and',
+                                                   'host_labels_@!@_vs_count': '1',
+                                                   'host_labels_@!@_vs_indexof_1': '1',
+                                                   'host_labels_@!@_vs_indexof_@:@': '',
+                                                   'host_labels_@!@_vs_orig_indexof_1': '1',
+                                                   'host_labels_@!@_vs_orig_indexof_@:@': '',
+                                                   'host_labels_count': '1',
+                                                   'host_labels_indexof_1': '1',
+                                                   'host_labels_indexof_@!@': '',
+                                                   'host_labels_orig_indexof_1': '1',
+                                                   'host_labels_orig_indexof_@!@': ''}},
+                       'name': 'avm_smart_home_devices_status',
+                       'position': (1, 14),
+                       'show_title': True,
+                       'single_infos': [],
+                       'size': (0, 0),
+                       'type': 'linked_view'},
+                      {'background': True,
+                       'context': {'host_labels': {'host_labels_1_bool': 'and',
+                                                   'host_labels_1_vs_1_bool': 'and',
+                                                   'host_labels_1_vs_1_vs': 'fritz/smarthome/device:yes',
+                                                   'host_labels_1_vs_2_bool': 'and',
+                                                   'host_labels_1_vs_@:@_bool': 'and',
+                                                   'host_labels_1_vs_count': '2',
+                                                   'host_labels_1_vs_indexof_1': '1',
+                                                   'host_labels_1_vs_indexof_2': '2',
+                                                   'host_labels_1_vs_indexof_@:@': '',
+                                                   'host_labels_1_vs_orig_indexof_1': '1',
+                                                   'host_labels_1_vs_orig_indexof_2': '2',
+                                                   'host_labels_1_vs_orig_indexof_@:@': '',
+                                                   'host_labels_@!@_bool': 'and',
+                                                   'host_labels_@!@_vs_1_bool': 'and',
+                                                   'host_labels_@!@_vs_@:@_bool': 'and',
+                                                   'host_labels_@!@_vs_count': '1',
+                                                   'host_labels_@!@_vs_indexof_1': '1',
+                                                   'host_labels_@!@_vs_indexof_@:@': '',
+                                                   'host_labels_@!@_vs_orig_indexof_1': '1',
+                                                   'host_labels_@!@_vs_orig_indexof_@:@': '',
+                                                   'host_labels_count': '1',
+                                                   'host_labels_indexof_1': '1',
+                                                   'host_labels_indexof_@!@': '',
+                                                   'host_labels_orig_indexof_1': '1',
+                                                   'host_labels_orig_indexof_@!@': ''}},
+                       'name': 'avm_smart_home_devices_metrics',
+                       'position': (1, 37),
+                       'show_title': True,
+                       'single_infos': [],
+                       'size': (0, 0),
+                       'type': 'linked_view'},
+                      {'background': True,
+                       'context': {'host_labels': {'host_labels_1_bool': 'and',
+                                                   'host_labels_1_vs_1_bool': 'and',
+                                                   'host_labels_1_vs_1_vs': 'fritz/smarthome/device:yes',
+                                                   'host_labels_1_vs_2_bool': 'and',
+                                                   'host_labels_1_vs_@:@_bool': 'and',
+                                                   'host_labels_1_vs_count': '2',
+                                                   'host_labels_1_vs_indexof_1': '1',
+                                                   'host_labels_1_vs_indexof_2': '2',
+                                                   'host_labels_1_vs_indexof_@:@': '',
+                                                   'host_labels_1_vs_orig_indexof_1': '1',
+                                                   'host_labels_1_vs_orig_indexof_2': '2',
+                                                   'host_labels_1_vs_orig_indexof_@:@': '',
+                                                   'host_labels_@!@_bool': 'and',
+                                                   'host_labels_@!@_vs_1_bool': 'and',
+                                                   'host_labels_@!@_vs_@:@_bool': 'and',
+                                                   'host_labels_@!@_vs_count': '1',
+                                                   'host_labels_@!@_vs_indexof_1': '1',
+                                                   'host_labels_@!@_vs_indexof_@:@': '',
+                                                   'host_labels_@!@_vs_orig_indexof_1': '1',
+                                                   'host_labels_@!@_vs_orig_indexof_@:@': '',
+                                                   'host_labels_count': '1',
+                                                   'host_labels_indexof_1': '1',
+                                                   'host_labels_indexof_@!@': '',
+                                                   'host_labels_orig_indexof_1': '1',
+                                                   'host_labels_orig_indexof_@!@': ''},
+                                   'service': {'service': 'Temperature'}},
+                       'graph_render_options': {'fixed_timerange': False,
+                                                'font_size': 8.0,
+                                                'show_controls': False,
+                                                'show_graph_time': True,
+                                                'show_legend': True,
+                                                'show_margin': False,
+                                                'show_pin': True,
+                                                'show_time_axis': True,
+                                                'show_vertical_axis': True,
+                                                'vertical_axis_width': 'fixed'},
+                       'graph_template': 'temperature',
+                       'position': (1, -1),
+                       'presentation': 'lines',
+                       'show_title': True,
+                       'single_infos': [],
+                       'size': (0, 0),
+                       'timerange': 90000,
+                       'type': 'combined_graph'},
+                      {'background': True,
+                       'context': {'host_labels': {'host_labels_1_bool': 'and',
+                                                   'host_labels_1_vs_1_bool': 'and',
+                                                   'host_labels_1_vs_1_vs': 'fritz/smarthome/device:yes',
+                                                   'host_labels_1_vs_2_bool': 'and',
+                                                   'host_labels_1_vs_@:@_bool': 'and',
+                                                   'host_labels_1_vs_count': '2',
+                                                   'host_labels_1_vs_indexof_1': '1',
+                                                   'host_labels_1_vs_indexof_2': '2',
+                                                   'host_labels_1_vs_indexof_@:@': '',
+                                                   'host_labels_1_vs_orig_indexof_1': '1',
+                                                   'host_labels_1_vs_orig_indexof_2': '2',
+                                                   'host_labels_1_vs_orig_indexof_@:@': '',
+                                                   'host_labels_@!@_bool': 'and',
+                                                   'host_labels_@!@_vs_1_bool': 'and',
+                                                   'host_labels_@!@_vs_@:@_bool': 'and',
+                                                   'host_labels_@!@_vs_count': '1',
+                                                   'host_labels_@!@_vs_indexof_1': '1',
+                                                   'host_labels_@!@_vs_indexof_@:@': '',
+                                                   'host_labels_@!@_vs_orig_indexof_1': '1',
+                                                   'host_labels_@!@_vs_orig_indexof_@:@': '',
+                                                   'host_labels_count': '1',
+                                                   'host_labels_indexof_1': '1',
+                                                   'host_labels_indexof_@!@': '',
+                                                   'host_labels_orig_indexof_1': '1',
+                                                   'host_labels_orig_indexof_@!@': ''},
+                                   'service': {'service': 'Energy'}},
+                       'graph_render_options': {'fixed_timerange': False,
+                                                'font_size': 8.0,
+                                                'show_controls': False,
+                                                'show_graph_time': True,
+                                                'show_legend': True,
+                                                'show_margin': False,
+                                                'show_pin': True,
+                                                'show_time_axis': True,
+                                                'show_vertical_axis': True,
+                                                'vertical_axis_width': 'fixed'},
+                       'graph_template': 'fritzbox_smart_home_energy_cost',
+                       'position': (54, 106),
+                       'presentation': 'sum',
+                       'show_title': True,
+                       'single_infos': [],
+                       'size': (0, 0),
+                       'timerange': 90000,
+                       'type': 'combined_graph'},
+                      {'background': True,
+                       'context': {},
+                       'name': 'invavmsmarthomedevices_filtered',
+                       'position': (1, 71),
+                       'show_title': True,
+                       'single_infos': [],
+                       'size': (0, 0),
+                       'type': 'linked_view'},
+                      {'background': True,
+                       'context': {'host_labels': {'host_labels_1_bool': 'and',
+                                                   'host_labels_1_vs_1_bool': 'and',
+                                                   'host_labels_1_vs_1_vs': 'fritz/smarthome/device:yes',
+                                                   'host_labels_1_vs_2_bool': 'and',
+                                                   'host_labels_1_vs_@:@_bool': 'and',
+                                                   'host_labels_1_vs_count': '2',
+                                                   'host_labels_1_vs_indexof_1': '1',
+                                                   'host_labels_1_vs_indexof_2': '2',
+                                                   'host_labels_1_vs_indexof_@:@': '',
+                                                   'host_labels_1_vs_orig_indexof_1': '1',
+                                                   'host_labels_1_vs_orig_indexof_2': '2',
+                                                   'host_labels_1_vs_orig_indexof_@:@': '',
+                                                   'host_labels_@!@_bool': 'and',
+                                                   'host_labels_@!@_vs_1_bool': 'and',
+                                                   'host_labels_@!@_vs_@:@_bool': 'and',
+                                                   'host_labels_@!@_vs_count': '1',
+                                                   'host_labels_@!@_vs_indexof_1': '1',
+                                                   'host_labels_@!@_vs_indexof_@:@': '',
+                                                   'host_labels_@!@_vs_orig_indexof_1': '1',
+                                                   'host_labels_@!@_vs_orig_indexof_@:@': '',
+                                                   'host_labels_count': '1',
+                                                   'host_labels_indexof_1': '1',
+                                                   'host_labels_indexof_@!@': '',
+                                                   'host_labels_orig_indexof_1': '1',
+                                                   'host_labels_orig_indexof_@!@': ''},
+                                   'service': {'service': 'Power'}},
+                       'graph_render_options': {'fixed_timerange': False,
+                                                'font_size': 8.0,
+                                                'show_controls': False,
+                                                'show_graph_time': True,
+                                                'show_legend': True,
+                                                'show_margin': False,
+                                                'show_pin': True,
+                                                'show_time_axis': True,
+                                                'show_vertical_axis': True,
+                                                'vertical_axis_width': 'fixed'},
+                       'graph_template': 'fritzbox_smart_home_electrical_power',
+                       'position': (1, 106),
+                       'presentation': 'stacked',
+                       'show_title': True,
+                       'single_infos': [],
+                       'size': (0, 0),
+                       'timerange': 90000,
+                       'type': 'combined_graph'},
+                      {'background': True,
+                       'context': {'host_labels': {'host_labels_1_bool': 'and',
+                                                   'host_labels_1_vs_1_bool': 'and',
+                                                   'host_labels_1_vs_@:@_bool': 'and',
+                                                   'host_labels_1_vs_count': '1',
+                                                   'host_labels_1_vs_indexof_1': '1',
+                                                   'host_labels_1_vs_indexof_@:@': '',
+                                                   'host_labels_1_vs_orig_indexof_1': '1',
+                                                   'host_labels_1_vs_orig_indexof_@:@': '',
+                                                   'host_labels_@!@_bool': 'and',
+                                                   'host_labels_@!@_vs_1_bool': 'and',
+                                                   'host_labels_@!@_vs_@:@_bool': 'and',
+                                                   'host_labels_@!@_vs_count': '1',
+                                                   'host_labels_@!@_vs_indexof_1': '1',
+                                                   'host_labels_@!@_vs_indexof_@:@': '',
+                                                   'host_labels_@!@_vs_orig_indexof_1': '1',
+                                                   'host_labels_@!@_vs_orig_indexof_@:@': '',
+                                                   'host_labels_count': '1',
+                                                   'host_labels_indexof_1': '1',
+                                                   'host_labels_indexof_@!@': '',
+                                                   'host_labels_orig_indexof_1': '1',
+                                                   'host_labels_orig_indexof_@!@': ''},
+                                   'serviceregex': {'neg_service_regex': '',
+                                                    'service_regex': 'Humidity'}},
+                       'graph_render_options': {'fixed_timerange': False,
+                                                'font_size': 8.0,
+                                                'show_controls': False,
+                                                'show_graph_time': True,
+                                                'show_legend': True,
+                                                'show_margin': False,
+                                                'show_pin': True,
+                                                'show_time_axis': True,
+                                                'show_vertical_axis': True,
+                                                'vertical_axis_width': 'fixed'},
+                       'graph_template': 'fritzbox_smart_home_humidity',
+                       'position': (54, -2),
+                       'presentation': 'lines',
+                       'show_title': True,
+                       'single_infos': [],
+                       'size': (0, 0),
+                       'timerange': 90000,
+                       'type': 'combined_graph'}],
+         'description': 'AVM Devices\n',
+         'hidden': False,
+         'hidebutton': False,
+         'icon': 'logo-avm_fritz',
+         'is_show_more': False,
+         'link_from': {},
+         'mandatory_context_filters': [],
+         'mtime': 1706207998,
+         'name': 'avm',
+         'packaged': False,
+         'public': True,
+         'show_title': True,
+         'single_infos': [],
+         'sort_index': 99,
+         'title': 'AVM',
+         'topic': 'other'}}
diff --git a/source/gui/metrics/fritzbox_smarthome.py b/source/gui/metrics/fritzbox_smarthome.py
index c3bb610..dd1872e 100644
--- a/source/gui/metrics/fritzbox_smarthome.py
+++ b/source/gui/metrics/fritzbox_smarthome.py
@@ -40,6 +40,11 @@ check_metrics["check_mk-fritzbox_smarthome_thermostat_multiple"] = {
     "temp_comfort": {"auto_graph": False},
 }
 
+metric_info["battery"] = {
+    "title": _("Battery"),
+    "color": "14/b",
+    "unit": "%",
+}
 metric_info["cost_last_reading"] = {
     "title": _("Cost last"),
     "color": "11/b",
@@ -92,7 +97,7 @@ metric_info["temp_target"] = {
     "unit": "c",
 }
 metric_info["temp_economic"] = {
-    "title": _("Temperature economic"),
+    "title": _("Temperature cool-down"),
     "color": "31/a",
     "unit": "c",
 }
@@ -101,21 +106,11 @@ metric_info["temp_comfort"] = {
     "color": "11/a",
     "unit": "c",
 }
-
-graph_info["fritzbox_smart_home_energy_surrent"] = {
-    "title": "Electrical energy consumption since last reading",
-    "metrics": [
-        ("energy_current", "area")
-    ]
-}
-
-graph_info["fritzbox_smart_home_energy_time_span"] = {
-    "title": "Electrical energy time between readings",
-    "metrics": [
-        ("energy_timespan", "area")
-    ]
+metric_info["temp_deviation"] = {
+    "title": _("Temperature deviation"),
+    "color": "35/a",
+    "unit": "c",
 }
-
 graph_info["fritzbox_smart_home_energy_cost"] = {
     "title": "Electrical energy cost",
     "metrics": [
@@ -132,6 +127,20 @@ graph_info["fritzbox_smart_home_energy_cost"] = {
     ],
 }
 
+graph_info["fritzbox_smart_home_energy_surrent"] = {
+    "title": "Electrical energy consumption since last reading",
+    "metrics": [
+        ("energy_current", "area")
+    ]
+}
+
+graph_info["fritzbox_smart_home_energy_time_span"] = {
+    "title": "Electrical energy time between readings",
+    "metrics": [
+        ("energy_timespan", "area")
+    ]
+}
+
 graph_info["fritzbox_smart_home_energy_total"] = {
     "title": "Electrical energy consumption total",
     "metrics": [
@@ -139,6 +148,18 @@ graph_info["fritzbox_smart_home_energy_total"] = {
     ]
 }
 
+graph_info["fritzbox_smart_home_electrical_power"] = {
+    "title": "Electrical power",
+    "metrics": [
+        ("power", "area")
+    ]
+}
+graph_info["fritzbox_smart_home_humidity"] = {
+    "title": "Relative humidity",
+    "metrics": [
+        ("humidity", "area")
+    ]
+}
 graph_info["fritzbox_smart_home_temp_control"] = {
     "title": _("Thermostat temperature control"),
     "metrics": [
@@ -147,7 +168,7 @@ graph_info["fritzbox_smart_home_temp_control"] = {
     ],
     "scalars": [
         ("temp_comfort", "Temperature comfort"),
-        ("temp_economic", "Temperature economic"),
+        ("temp_economic", "Temperature cool-down"),
     ],
     "optional_metrics": [
         "temp_target",
@@ -173,3 +194,9 @@ perfometer_info.append({
     "half_value": 100,
     "exponent": 3,
 })
+
+perfometer_info.append({
+    "type": "linear",
+    'segments': ['battery'],
+    'total': 100,
+})
\ No newline at end of file
diff --git a/source/gui/views/avm_fritzbox b/source/gui/views/avm_fritzbox
new file mode 100644
index 0000000..edba899
--- /dev/null
+++ b/source/gui/views/avm_fritzbox
@@ -0,0 +1,59 @@
+{'avm_fritzbox': {'add_context_to_title': False,
+                  'browser_reload': 0,
+                  'column_headers': 'pergroup',
+                  'context': {'host_labels': {'host_labels_1_bool': 'and',
+                                              'host_labels_1_vs_1_bool': 'and',
+                                              'host_labels_1_vs_1_vs': 'cmk/os_family:FRITZ!OS',
+                                              'host_labels_1_vs_2_bool': 'and',
+                                              'host_labels_1_vs_@:@_bool': 'and',
+                                              'host_labels_1_vs_count': '2',
+                                              'host_labels_1_vs_indexof_1': '1',
+                                              'host_labels_1_vs_indexof_2': '2',
+                                              'host_labels_1_vs_indexof_@:@': '',
+                                              'host_labels_1_vs_orig_indexof_1': '1',
+                                              'host_labels_1_vs_orig_indexof_2': '2',
+                                              'host_labels_1_vs_orig_indexof_@:@': '',
+                                              'host_labels_@!@_bool': 'and',
+                                              'host_labels_@!@_vs_1_bool': 'and',
+                                              'host_labels_@!@_vs_@:@_bool': 'and',
+                                              'host_labels_@!@_vs_count': '1',
+                                              'host_labels_@!@_vs_indexof_1': '1',
+                                              'host_labels_@!@_vs_indexof_@:@': '',
+                                              'host_labels_@!@_vs_orig_indexof_1': '1',
+                                              'host_labels_@!@_vs_orig_indexof_@:@': '',
+                                              'host_labels_count': '1',
+                                              'host_labels_indexof_1': '1',
+                                              'host_labels_indexof_@!@': '',
+                                              'host_labels_orig_indexof_1': '1',
+                                              'host_labels_orig_indexof_@!@': ''}},
+                  'datasource': 'hosts',
+                  'description': 'Displaying the overall state of AVM Fritzbox '
+                                 'Devices\n',
+                  'force_checkboxes': False,
+                  'group_painters': [],
+                  'hidden': True,
+                  'hidebutton': True,
+                  'icon': 'checkmk',
+                  'is_show_more': False,
+                  'layout': 'table',
+                  'link_from': {},
+                  'mobile': False,
+                  'mustsearch': False,
+                  'name': 'avm_fritzbox',
+                  'num_columns': 1,
+                  'packaged': False,
+                  'painters': [{'name': 'host', 'parameters': {'color_choices': ['colorize_up', 'colorize_down', 'colorize_unreachable', 'colorize_pending', 'colorize_downtime']}, 'link_spec': ('views', 'host'), 'tooltip': 'host_addresses', 'join_value': None, 'column_title': '', 'column_type': 'column'},
+                               {'name': 'svc_plugin_output', 'parameters': {}, 'link_spec': None, 'tooltip': None, 'join_value': 'Connection', 'column_title': '', 'column_type': 'join_column'},
+                               {'name': 'svc_plugin_output', 'parameters': {}, 'link_spec': None, 'tooltip': None, 'join_value': 'Link Info', 'column_title': '', 'column_type': 'join_column'},
+                               {'name': 'perfometer', 'parameters': {}, 'link_spec': None, 'tooltip': None, 'join_value': 'Interface WAN', 'column_title': '', 'column_type': 'join_column'},
+                               {'name': 'perfometer', 'parameters': {}, 'link_spec': None, 'tooltip': None, 'join_value': 'NTP server', 'column_title': '', 'column_type': 'join_column'},
+                               {'name': 'perfometer', 'parameters': {}, 'link_spec': None, 'tooltip': None, 'join_value': 'Uptime', 'column_title': '', 'column_type': 'join_column'}],
+                  'play_sounds': False,
+                  'public': False,
+                  'single_infos': [],
+                  'sort_index': 6,
+                  'sorters': [('sitealias', False, None),
+                              ('host_name', False, None)],
+                  'title': 'AVM Fritzbox',
+                  'topic': 'analyze',
+                  'user_sortable': True}}
diff --git a/source/gui/views/avm_smart_home_devices_metrics b/source/gui/views/avm_smart_home_devices_metrics
new file mode 100644
index 0000000..ded95fb
--- /dev/null
+++ b/source/gui/views/avm_smart_home_devices_metrics
@@ -0,0 +1,62 @@
+{'avm_smart_home_devices_metrics': {'add_context_to_title': False,
+                                    'browser_reload': 0,
+                                    'column_headers': 'pergroup',
+                                    'context': {'host_labels': {'host_labels_1_bool': 'and',
+                                                                'host_labels_1_vs_1_bool': 'and',
+                                                                'host_labels_1_vs_1_vs': 'fritz/smarthome/device:yes',
+                                                                'host_labels_1_vs_2_bool': 'and',
+                                                                'host_labels_1_vs_@:@_bool': 'and',
+                                                                'host_labels_1_vs_count': '2',
+                                                                'host_labels_1_vs_indexof_1': '1',
+                                                                'host_labels_1_vs_indexof_2': '2',
+                                                                'host_labels_1_vs_indexof_@:@': '',
+                                                                'host_labels_1_vs_orig_indexof_1': '1',
+                                                                'host_labels_1_vs_orig_indexof_2': '2',
+                                                                'host_labels_1_vs_orig_indexof_@:@': '',
+                                                                'host_labels_@!@_bool': 'and',
+                                                                'host_labels_@!@_vs_1_bool': 'and',
+                                                                'host_labels_@!@_vs_@:@_bool': 'and',
+                                                                'host_labels_@!@_vs_count': '1',
+                                                                'host_labels_@!@_vs_indexof_1': '1',
+                                                                'host_labels_@!@_vs_indexof_@:@': '',
+                                                                'host_labels_@!@_vs_orig_indexof_1': '1',
+                                                                'host_labels_@!@_vs_orig_indexof_@:@': '',
+                                                                'host_labels_count': '1',
+                                                                'host_labels_indexof_1': '1',
+                                                                'host_labels_indexof_@!@': '',
+                                                                'host_labels_orig_indexof_1': '1',
+                                                                'host_labels_orig_indexof_@!@': ''}},
+                                    'datasource': 'hosts',
+                                    'description': 'Displaying the overall '
+                                                   'state ofAVM SmartHome '
+                                                   'Devices\n',
+                                    'force_checkboxes': False,
+                                    'group_painters': [],
+                                    'hidden': True,
+                                    'hidebutton': True,
+                                    'icon': 'checkmk',
+                                    'is_show_more': False,
+                                    'layout': 'table',
+                                    'link_from': {},
+                                    'mobile': False,
+                                    'mustsearch': False,
+                                    'name': 'avm_smart_home_devices_metrics',
+                                    'num_columns': 1,
+                                    'packaged': False,
+                                    'painters': [{'name': 'host', 'parameters': {'color_choices': ['colorize_up', 'colorize_down', 'colorize_unreachable', 'colorize_pending', 'colorize_downtime']}, 'link_spec': ('views', 'host'), 'tooltip': 'host_addresses', 'join_value': None, 'column_title': '', 'column_type': 'column'},
+                                                 {'name': 'perfometer', 'parameters': {}, 'link_spec': None, 'tooltip': None, 'join_value': '~Battery', 'column_title': '', 'column_type': 'join_column'},
+                                                 {'name': 'perfometer', 'parameters': {}, 'link_spec': None, 'tooltip': None, 'join_value': '~Energy', 'column_title': '', 'column_type': 'join_column'},
+                                                 {'name': 'perfometer', 'parameters': {}, 'link_spec': None, 'tooltip': None, 'join_value': '~Humidity', 'column_title': '', 'column_type': 'join_column'},
+                                                 {'name': 'perfometer', 'parameters': {}, 'link_spec': None, 'tooltip': None, 'join_value': '~Power', 'column_title': '', 'column_type': 'join_column'},
+                                                 {'name': 'perfometer', 'parameters': {}, 'link_spec': None, 'tooltip': None, 'join_value': '~Temperature', 'column_title': '', 'column_type': 'join_column'},
+                                                 {'name': 'perfometer', 'parameters': {}, 'link_spec': None, 'tooltip': None, 'join_value': '~Thermostat', 'column_title': '', 'column_type': 'join_column'},
+                                                 {'name': 'perfometer', 'parameters': {}, 'link_spec': None, 'tooltip': None, 'join_value': '~Voltage', 'column_title': '', 'column_type': 'join_column'}],
+                                    'play_sounds': False,
+                                    'public': False,
+                                    'single_infos': [],
+                                    'sort_index': 6,
+                                    'sorters': [('sitealias', False, None),
+                                                ('host_name', False, None)],
+                                    'title': 'AVM SmartHome Devices (Metrics)',
+                                    'topic': 'analyze',
+                                    'user_sortable': True}}
diff --git a/source/gui/views/avm_smart_home_devices_status b/source/gui/views/avm_smart_home_devices_status
new file mode 100644
index 0000000..97f51e7
--- /dev/null
+++ b/source/gui/views/avm_smart_home_devices_status
@@ -0,0 +1,63 @@
+{'avm_smart_home_devices_status': {'add_context_to_title': False,
+                                   'browser_reload': 0,
+                                   'column_headers': 'pergroup',
+                                   'context': {'host_labels': {'host_labels_1_bool': 'and',
+                                                               'host_labels_1_vs_1_bool': 'and',
+                                                               'host_labels_1_vs_1_vs': 'fritz/smarthome/device:yes',
+                                                               'host_labels_1_vs_2_bool': 'and',
+                                                               'host_labels_1_vs_@:@_bool': 'and',
+                                                               'host_labels_1_vs_count': '2',
+                                                               'host_labels_1_vs_indexof_1': '1',
+                                                               'host_labels_1_vs_indexof_2': '2',
+                                                               'host_labels_1_vs_indexof_@:@': '',
+                                                               'host_labels_1_vs_orig_indexof_1': '1',
+                                                               'host_labels_1_vs_orig_indexof_2': '2',
+                                                               'host_labels_1_vs_orig_indexof_@:@': '',
+                                                               'host_labels_@!@_bool': 'and',
+                                                               'host_labels_@!@_vs_1_bool': 'and',
+                                                               'host_labels_@!@_vs_@:@_bool': 'and',
+                                                               'host_labels_@!@_vs_count': '1',
+                                                               'host_labels_@!@_vs_indexof_1': '1',
+                                                               'host_labels_@!@_vs_indexof_@:@': '',
+                                                               'host_labels_@!@_vs_orig_indexof_1': '1',
+                                                               'host_labels_@!@_vs_orig_indexof_@:@': '',
+                                                               'host_labels_count': '1',
+                                                               'host_labels_indexof_1': '1',
+                                                               'host_labels_indexof_@!@': '',
+                                                               'host_labels_orig_indexof_1': '1',
+                                                               'host_labels_orig_indexof_@!@': ''}},
+                                   'datasource': 'hosts',
+                                   'description': 'Displaying the overall '
+                                                  'state ofAVM SmartHome '
+                                                  'Devices\n',
+                                   'force_checkboxes': False,
+                                   'group_painters': [],
+                                   'hidden': True,
+                                   'hidebutton': True,
+                                   'icon': 'checkmk',
+                                   'is_show_more': False,
+                                   'layout': 'table',
+                                   'link_from': {},
+                                   'mobile': False,
+                                   'mustsearch': False,
+                                   'name': 'avm_smart_home_devices_status',
+                                   'num_columns': 1,
+                                   'packaged': False,
+                                   'painters': [{'name': 'host', 'parameters': {'color_choices': ['colorize_up', 'colorize_down', 'colorize_unreachable', 'colorize_pending', 'colorize_downtime']}, 'link_spec': ('views', 'host'), 'tooltip': 'host_addresses', 'join_value': None, 'column_title': '', 'column_type': 'column'},
+                                                {'name': 'svc_plugin_output', 'parameters': {}, 'link_spec': None, 'tooltip': None, 'join_value': '~Device status', 'column_title': '', 'column_type': 'join_column'},
+                                                {'name': 'svc_plugin_output', 'parameters': {}, 'link_spec': None, 'tooltip': None, 'join_value': '~Power socket', 'column_title': '', 'column_type': 'join_column'},
+                                                {'name': 'service_state', 'parameters': {}, 'link_spec': None, 'tooltip': None, 'join_value': '~Battery', 'column_title': '', 'column_type': 'join_column'},
+                                                {'name': 'service_state', 'parameters': {}, 'link_spec': None, 'tooltip': None, 'join_value': '~Humidity', 'column_title': '', 'column_type': 'join_column'},
+                                                {'name': 'service_state', 'parameters': {}, 'link_spec': None, 'tooltip': None, 'join_value': '~Temperature', 'column_title': '', 'column_type': 'join_column'},
+                                                {'name': 'service_state', 'parameters': {}, 'link_spec': None, 'tooltip': None, 'join_value': '~Thermostat', 'column_title': '', 'column_type': 'join_column'},
+                                                {'name': 'service_state', 'parameters': {}, 'link_spec': None, 'tooltip': None, 'join_value': '~Power', 'column_title': '', 'column_type': 'join_column'},
+                                                {'name': 'service_state', 'parameters': {}, 'link_spec': None, 'tooltip': None, 'join_value': '~Voltage', 'column_title': '', 'column_type': 'join_column'}],
+                                   'play_sounds': False,
+                                   'public': False,
+                                   'single_infos': [],
+                                   'sort_index': 6,
+                                   'sorters': [('sitealias', False, None),
+                                               ('host_name', False, None)],
+                                   'title': 'AVM SmartHome Devices (status)',
+                                   'topic': 'analyze',
+                                   'user_sortable': True}}
diff --git a/source/gui/views/invavmsmarthomedevices_filtered b/source/gui/views/invavmsmarthomedevices_filtered
new file mode 100644
index 0000000..603c72d
--- /dev/null
+++ b/source/gui/views/invavmsmarthomedevices_filtered
@@ -0,0 +1,69 @@
+{'invavmsmarthomedevices_filtered': {'add_context_to_title': True,
+                                     'browser_reload': 0,
+                                     'column_headers': 'pergroup',
+                                     'context': {'host_labels': {'host_labels_1_bool': 'and',
+                                                                 'host_labels_1_vs_1_bool': 'and',
+                                                                 'host_labels_1_vs_1_vs': 'fritz/smarthome/device:yes',
+                                                                 'host_labels_1_vs_2_bool': 'and',
+                                                                 'host_labels_1_vs_@:@_bool': 'and',
+                                                                 'host_labels_1_vs_count': '2',
+                                                                 'host_labels_1_vs_indexof_1': '1',
+                                                                 'host_labels_1_vs_indexof_2': '2',
+                                                                 'host_labels_1_vs_indexof_@:@': '',
+                                                                 'host_labels_1_vs_orig_indexof_1': '1',
+                                                                 'host_labels_1_vs_orig_indexof_2': '2',
+                                                                 'host_labels_1_vs_orig_indexof_@:@': '',
+                                                                 'host_labels_@!@_bool': 'and',
+                                                                 'host_labels_@!@_vs_1_bool': 'and',
+                                                                 'host_labels_@!@_vs_@:@_bool': 'and',
+                                                                 'host_labels_@!@_vs_count': '1',
+                                                                 'host_labels_@!@_vs_indexof_1': '1',
+                                                                 'host_labels_@!@_vs_indexof_@:@': '',
+                                                                 'host_labels_@!@_vs_orig_indexof_1': '1',
+                                                                 'host_labels_@!@_vs_orig_indexof_@:@': '',
+                                                                 'host_labels_count': '1',
+                                                                 'host_labels_indexof_1': '1',
+                                                                 'host_labels_indexof_@!@': '',
+                                                                 'host_labels_orig_indexof_1': '1',
+                                                                 'host_labels_orig_indexof_@!@': ''},
+                                                 'invavmsmarthomedevices_functions': {'invavmsmarthomedevices_functions': ''},
+                                                 'invavmsmarthomedevices_fw_version': {'invavmsmarthomedevices_fw_version': ''},
+                                                 'invavmsmarthomedevices_id': {'invavmsmarthomedevices_id': ''},
+                                                 'invavmsmarthomedevices_identifier': {'invavmsmarthomedevices_identifier': ''},
+                                                 'invavmsmarthomedevices_manufacturer': {'invavmsmarthomedevices_manufacturer': ''},
+                                                 'invavmsmarthomedevices_name': {'invavmsmarthomedevices_name': ''},
+                                                 'invavmsmarthomedevices_product_name': {'invavmsmarthomedevices_product_name': ''}},
+                                     'datasource': 'invavmsmarthomedevices',
+                                     'description': 'A view for searching in '
+                                                    'the inventory data for '
+                                                    'Smart home devices '
+                                                    '(filtered)\n',
+                                     'force_checkboxes': False,
+                                     'group_painters': [],
+                                     'hidden': False,
+                                     'hidebutton': False,
+                                     'icon': None,
+                                     'inventory_join_macros': {'macros': []},
+                                     'is_show_more': True,
+                                     'layout': 'table',
+                                     'link_from': {},
+                                     'mobile': False,
+                                     'mustsearch': False,
+                                     'name': 'invavmsmarthomedevices_filtered',
+                                     'num_columns': 1,
+                                     'packaged': False,
+                                     'painters': [{'name': 'host', 'parameters': {'color_choices': []}, 'link_spec': ('views', 'inv_host'), 'tooltip': None, 'join_value': None, 'column_title': '', 'column_type': 'column'},
+                                                  {'name': 'invavmsmarthomedevices_id', 'parameters': {}, 'link_spec': None, 'tooltip': None, 'join_value': None, 'column_title': '', 'column_type': 'column'},
+                                                  {'name': 'invavmsmarthomedevices_product_name', 'parameters': {}, 'link_spec': None, 'tooltip': None, 'join_value': None, 'column_title': '', 'column_type': 'column'},
+                                                  {'name': 'invavmsmarthomedevices_fw_version', 'parameters': {}, 'link_spec': None, 'tooltip': None, 'join_value': None, 'column_title': '', 'column_type': 'column'},
+                                                  {'name': 'invavmsmarthomedevices_identifier', 'parameters': {}, 'link_spec': None, 'tooltip': None, 'join_value': None, 'column_title': '', 'column_type': 'column'},
+                                                  {'name': 'invavmsmarthomedevices_functions', 'parameters': {}, 'link_spec': None, 'tooltip': None, 'join_value': None, 'column_title': '', 'column_type': 'column'}],
+                                     'play_sounds': False,
+                                     'public': False,
+                                     'single_infos': [],
+                                     'sort_index': 30,
+                                     'sorters': [],
+                                     'title': 'Search Smart home devices '
+                                              '(filtered)',
+                                     'topic': 'inventory',
+                                     'user_sortable': True}}
diff --git a/source/gui/wato/check_parameters/fritzbox_smarthome.py b/source/gui/wato/check_parameters/fritzbox_smarthome.py
index cf75d6a..eed2e85 100644
--- a/source/gui/wato/check_parameters/fritzbox_smarthome.py
+++ b/source/gui/wato/check_parameters/fritzbox_smarthome.py
@@ -78,6 +78,16 @@ def _parameter_valuespec_fritzbox_smarthome_thermostat():
                  title=_('Monitoring state if thermostat is off'),
                  default_value=0,
              )),
+            ('state_windows_open',
+             MonitoringState(
+                 title=_('Monitoring state if windows open active'),
+                 default_value=1,
+             )),
+            ('state_boost_mode',
+             MonitoringState(
+                 title=_('Monitoring state if boost mode active'),
+                 default_value=1,
+             )),
             ('state_on_error',
              MonitoringState(
                  title=_('Monitoring state on error'),
@@ -119,6 +129,13 @@ def _parameter_valuespec_fritzbox_smarthome_battery():
                  title=_('Monitoring state on low battery'),
                  default_value=2,
              )),
+            ('levels_lower',
+             Tuple(
+                 title=_('Lower levels for battery'),
+                 elements=[
+                     Integer(title=_('Warning below'), default_value=50, unit=_('%')),
+                     Integer(title=_('Critical below'), default_value=40, unit=_('%')),
+                 ])),
         ],
     )
 
diff --git a/source/lib/python3/cmk/special_agents/agent_fritzbox_smarthome.py b/source/lib/python3/cmk/special_agents/agent_fritzbox_smarthome.py
index 4608565..f335250 100644
--- a/source/lib/python3/cmk/special_agents/agent_fritzbox_smarthome.py
+++ b/source/lib/python3/cmk/special_agents/agent_fritzbox_smarthome.py
@@ -5,26 +5,107 @@
 # 2023-12-18: modified to work with cmk 2.2.x
 #             changed to return the complete XML response back as json
 # 2023-12-28: added data/option for testing
+# 2024-01-11: reworked to support PBKDF2
 
-import sys
-import traceback
-import ssl
-import json
-import time
 
-from urllib.request import urlopen
-import argparse
-import xml.etree.ElementTree as ET
-import hashlib
+from argparse import ArgumentParser, RawTextHelpFormatter
+from collections import Counter
+from hashlib import pbkdf2_hmac, md5
+from json import dumps
 from re import sub as re_sub
+from requests import exceptions as r_exceptions,  Response, session
+from sys import exit, stderr, stdout
+from time import sleep
+from urllib3 import disable_warnings
+from xml.etree import ElementTree
+
 from cmk.utils.password_store import replace_passwords
 
 
+class AvmSession:
+    def __init__(
+            self,
+            host: str,
+            ignore_ssl: bool = False,
+            protocol: str = 'https',
+            port: str = '443',
+            no_pbkdf2: bool = False,
+    ):
+        self._session = session()
+        self._base_url = f'{protocol}://{host}:{port}'
+        self._verify = not ignore_ssl
+        self._pbkdf2 = not no_pbkdf2
+        self._sid = ''
+
+        if not self._verify:
+            disable_warnings()
+        if self._pbkdf2:
+            self._version = '&version=2'
+        else:
+            self._version = ''
+
+    def _get(self, url) -> Response:
+        try:
+            response = self._session.get(url=url, verify=self._verify)
+        except (r_exceptions.ConnectionError, r_exceptions.SSLError) as e:
+            stderr.write(f'fritzbox_smarthome\n {e}\n')
+            exit(1)
+
+        if response.status_code != 200:
+            stdout.write(f'can not connect, status: {response.status_code}, {response.text}')
+            exit(1)
+        return response
+
+    def get(self, url: str) -> Response:
+        return self._get(url=f'{self._base_url}/{url}{self._version}&sid={self._sid}')
+
+    def login(self, username: str, password: str):
+        # CALL /login_sid.lua and grab challenge
+        response = self._get(url=f'{self._base_url}/login_sid.lua?{self._version}')
+
+        xml_login = str_to_xml(response.text)
+        check_block_time(xml=xml_login)  # stop if block time > 10
+
+        challenge = xml_login.find('Challenge').text
+
+        if self._pbkdf2:
+            challenge_response = calculate_pbkdf2_response(challenge=challenge, password=password)
+        else:
+            challenge_response = calculate_md5_response(challenge=challenge, password=password)
+
+        # CALL /login_sid.lua?username=<username>&response=<challenge_response>
+        # and grab session-id
+        url = f'{self._base_url}/login_sid.lua?username={username}&response={challenge_response}{self._version}'
+        response = self._get(url=url)
+        xml_login_solve = str_to_xml(response.text)
+        check_block_time(xml=xml_login_solve)  # stop if block time > 10
+        self._sid = xml_login_solve.find('SID').text
+        if self._sid == '0000000000000000':
+            raise Exception('Check credentials\n')
+
+    def logout(self):
+        url = f'/login_sid.lua?logout=logout'
+        self.get(url=url)
+        self._session.close()
+
+
 # based on: https://stackoverflow.com/a/47081240
 def parse_xml_to_json(xml):
     response = {}
     for key in xml.keys():
         response[key] = xml.get(key)
+
+    # add index to duplicate child names (i.e. button)
+    tags = [child.tag for child in list(xml)]
+    duplicates = [k for k, v in Counter(tags).items() if v > 1]
+    if duplicates:
+        for tag in duplicates:
+            index = 0
+            for child in list(xml):
+                if child.tag == tag:
+                    child.tag = f'{child.tag}{index}'
+                    index += 1
+
     for child in list(xml):
         for key in child.keys():
             response[key] = child.get(key)
@@ -37,17 +118,34 @@ def parse_xml_to_json(xml):
     return response
 
 
+def str_to_xml(text: str) -> ElementTree.Element:
+    try:
+        return ElementTree.fromstring(text)
+    except ElementTree.ParseError as e:
+        stderr.write(f'XML parse error. {e}')
+        exit(1)
+
+
 def parse_args():
-    parser = argparse.ArgumentParser(
+    parser = ArgumentParser(
         description='Check_MK Fritz!Box Smarthome Agent\n'
                     'This is an additional check_MK Fritz!Box Agent which can gather information\'s over the \n'
                     'AVM AHA HTTP Interface about SmartHome Devices connected to an Fritz!Box.',
-        formatter_class=argparse.RawTextHelpFormatter,
+        formatter_class=RawTextHelpFormatter,
     )
     parser.add_argument(
-        'host',
+        'host', type=str,
         help='Host name or IP address of your Fritz!Box',
     )
+    parser.add_argument(
+        '--username', type=str, required=True,
+        help='The username to logon to the Fritz!Box',
+    )
+    parser.add_argument(
+        '--password', type=str, required=True,
+        help='The password to logon the Fritz!Box',
+    )
+
     parser.add_argument(
         '--debug', action='store_true', default=False,
         help='Debug mode: let Python exceptions come through',
@@ -63,222 +161,202 @@ def parse_args():
              ' to your Fritz!Box use this option.',
     )
     parser.add_argument(
-        '--password', nargs='?',
-        help='The password to logon the Fritz!Box',
-    )
-    parser.add_argument(
-        '--username', nargs='?',
-        help='The username to logon to the Fritz!Box',
-    )
-    parser.add_argument(
-        '--port', nargs='?', type=int, default=443,
+        '--port', type=int, default=443,
         help='The TCP port on witch to access the Fritz!Box',
     )
     parser.add_argument(
-        '--prefix', nargs='?',
+        '--prefix', type=str,
         help='The prefix is used to group all the Smarthome devices from one Fritz!Box in CMK.'
         )
     parser.add_argument(
-        '--protocol', nargs='?', choices=['http', 'https'], default='https',
+        '--protocol', type=str, choices=['http', 'https'], default='https',
         help='The protocol used to access the Fritz!Box',
     )
-
+    parser.add_argument(
+        '--no-pbkdf2', action='store_true', default=False,
+        help='This will disable the use of PBDKF2 (Password-Based Key Derivation Function 2) and '
+             'fall back to MD5 (less secure)'
+    )
     parser.add_argument(
         '--testing', action='store_true', default=False,
         help='Development usage only (might be ignored)'
     )
+
     args = parser.parse_args()
 
     return args
 
 
-def check_fritzbox_smarthome(args):
-    base_address = '%s://%s:%d' % (args.protocol, args.host, args.port)
-
-    ctx = ssl.create_default_context()
-    if args.ignore_ssl:
-        ctx.check_hostname = False
-        ctx.verify_mode = ssl.CERT_NONE
-
-    # CALL /login_sid.lua
-    # and grab challenge
-    response = urlopen(base_address + '/login_sid.lua', context=ctx)
-    if args.password:
-        xml_login = ET.fromstring(response.read())
-        challenge = xml_login.find('Challenge').text
-        blocktime = int(xml_login.find('BlockTime').text)
-        if blocktime > 0:
-            sys.stdout.write('<<<fritzbox_smarthome:sep(0)>>>')
-            sys.stdout.write(json.dumps({'block_time': blocktime}))
-            exit()
+def check_block_time(xml: ElementTree.fromstring) -> bool:
+    block_time = int(xml.find('BlockTime').text)
+    if 10 < block_time > 0:
+        sleep(block_time)
+    elif block_time > 10:
+        stdout.write('<<<fritzbox_smarthome:sep(0)>>>')
+        stdout.write(dumps({'block_time': block_time}))
+        exit()
 
-        # create challenge_response (hash with md5: '<challenge>-<password>')
-        # TODO: check if challenge is PBKDF2 (startswith $2)
-        digest = hashlib.md5()
-        digest.update(challenge.encode('utf-16le'))
-        digest.update('-'.encode('utf-16le'))
-        digest.update(args.password.encode('utf-16le'))
+    return False
 
-        challenge_response = challenge + '-' + digest.hexdigest()
 
-        # CALL /login_sid.lua?username=<username>&response=<challenge_response>
-        # and grab sessionid
-        if args.username:
-            response = urlopen(
-                base_address + '/login_sid.lua?username=%s&response=%s' % (args.username, challenge_response),
-                context=ctx)
-        else:
-            response = urlopen(base_address + '/login_sid.lua?response=%s' % challenge_response, context=ctx)
+def calculate_md5_response(challenge: str, password: str) -> str:
+    digest = md5()
+    digest.update(challenge.encode('utf-16le'))
+    digest.update('-'.encode('utf-16le'))
+    digest.update(password.encode('utf-16le'))
 
-    xml_login_solve = ET.fromstring(response.read())
-    sessionid = xml_login_solve.find('SID').text
+    return challenge + '-' + digest.hexdigest()
 
-    blocktime = int(xml_login_solve.find('BlockTime').text)
-    if blocktime > 0:
-        sys.stdout.write('<<<fritzbox_smarthome:sep(0)>>>')
-        sys.stdout.write(json.dumps({'block_time': blocktime}))
-        exit()
 
-    if args.password and sessionid == '0000000000000000':
-        raise Exception('Check credentials\n')
+def calculate_pbkdf2_response(challenge: str, password: str) -> str:
+    """ Calculate the response for a given challenge via PBKDF2 """
+    # Extract all necessary values encoded into the challenge
+    version, iter1, salt1, iter2, salt2 = challenge.split('$')
+    # Hash twice, once with static salt...
+    hash1 = pbkdf2_hmac('sha256', password.encode(), bytes.fromhex(salt1), int(iter1))
+    # Once with dynamic salt.
+    hash2 = pbkdf2_hmac('sha256', hash1, bytes.fromhex(salt2), int(iter2))
+    return f'{salt2}${hash2.hex()}'
+
+
+def check_fritzbox_smarthome(args):
+
+    avm_session = AvmSession(
+        ignore_ssl=args.ignore_ssl,
+        host=args.host,
+        protocol=args.protocol,
+        port=args.port,
+        no_pbkdf2=args.no_pbkdf2,
+    )
+
+    avm_session.login(username=args.username, password=args.password)
+
+    # get device data
+    response = avm_session.get(url=f'/webservices/homeautoswitch.lua?switchcmd=getdevicelistinfos')
+
+    response_read = response.text
 
-    # Write section header
-    response = urlopen(
-        base_address + '/webservices/homeautoswitch.lua?switchcmd=getdevicelistinfos&sid=%s' % sessionid, context=ctx)
-    response_read = response.read()
     if args.debug:
-        sys.stdout.write('Raw XML:\n')
-        sys.stdout.write(str(response_read))
-        sys.stdout.write('\n')
+        stdout.write('Raw XML:\n')
+        stdout.write(str(response_read))
+        stdout.write('\n')
 
-    xml_devicelist = ET.fromstring(response_read)
+    xml_device_list = str_to_xml(response_read)
     devices = []
 
     if args.testing:
         __switch_01 = {
-            "identifier": "08761 0116372",
-            "id": "99",
-            "functionbitmask": "35712",
-            "fwversion": "04.26",
-            "manufacturer": "AVM",
-            "productname": "FRITZ!DECT 200",
-            "present": "1",
-            "txbusy": "0",
-            "name": "TV-living_room",
-            "switch": {
-                "state": "1",
-                "mode": "manuell",
-                "lock": "0",
-                "devicelock": "0"
+            'identifier': '08761 0116372',
+            'id': '99',
+            'functionbitmask': '35712',
+            'fwversion': '04.26',
+            'manufacturer': 'AVM',
+            'productname': 'FRITZ!DECT 200',
+            'present': '1',
+            'txbusy': '0',
+            'name': 'TV-living_room',
+            'switch': {
+                'state': '1',
+                'mode': 'manuell',
+                'lock': '0',
+                'devicelock': '0'
             },
-            "simpleonoff": {
-                "state": "1"
+            'simpleonoff': {
+                'state': '1'
             },
-            "powermeter": {
-                "voltage": "235814",
-                "power": "4220",
-                "energy": "145427"
+            'powermeter': {
+                'voltage': '235814',
+                'power': '4220',
+                'energy': '145427'
             },
-            "temperature": {
-                "celsius": "190",
-                "offset": "0"
+            'temperature': {
+                'celsius': '190',
+                'offset': '0'
             }
         }
         __repeater_01 = {
-            "identifier": "11657 0057950",
-            "id": "98",
-            "functionbitmask": "1024",
-            "fwversion": "04.16",
-            "manufacturer": "AVM",
-            "productname": "FRITZ!DECT Repeater 100",
-            "present": "0",
-            "txbusy": "0",
-            "name": "FRITZ!DECT Rep 100 #1"
+            'identifier': '11657 0057950',
+            'id': '98',
+            'functionbitmask': '1024',
+            'fwversion': '04.16',
+            'manufacturer': 'AVM',
+            'productname': 'FRITZ!DECT Repeater 100',
+            'present': '0',
+            'txbusy': '0',
+            'name': 'FRITZ!DECT Rep 100 #1'
         }
         __repeater_02 = {
-            "identifier": "11657 0170905",
-            "id": "97",
-            "functionbitmask": "1280",
-            "fwversion": "04.25",
-            "manufacturer": "AVM",
-            "productname": "FRITZ!DECT Repeater 100",
-            "present": "1",
-            "txbusy": "0",
-            "name": "FRITZ!DECT Repeater 100 #2",
-            "temperature": {
-                "celsius": "245",
-                "offset": "0"
+            'identifier': '11657 0170905',
+            'id': '97',
+            'functionbitmask': '1280',
+            'fwversion': '04.25',
+            'manufacturer': 'AVM',
+            'productname': 'FRITZ!DECT Repeater 100',
+            'present': '1',
+            'txbusy': '0',
+            'name': 'FRITZ!DECT Repeater 100 #2',
+            'temperature': {
+                'celsius': '245',
+                'offset': '0'
             }
         }
         __thermostat_01 = {
-            "identifier": "13979 0878454",
-            "id": "96",
-            "functionbitmask": "320",
-            "fwversion": "05.16",
-            "manufacturer": "AVM",
-            "productname": "Comet DECT",
-            "present": "1",
-            "name": "Temp02",
-            "temperature": {
-                "celsius": "210",
-                "offset": "-10"
+            'identifier': '13979 0878454',
+            'id': '96',
+            'functionbitmask': '320',
+            'fwversion': '05.16',
+            'manufacturer': 'AVM',
+            'productname': 'Comet DECT',
+            'present': '1',
+            'name': 'Temp02',
+            'temperature': {
+                'celsius': '210',
+                'offset': '-10'
             },
-            "hkr": {
-                "tist": "42",
-                "tsoll": "32",
-                "absenk": "32",
-                "komfort": "38",
-                "lock": "1",
-                "devicelock": "1",
-                "errorcode": "0",
-                "batterylow": "0",
-                "nextchange": {
-                    "endperiod": "1704888000",
-                    "tchange": "32"
+            'hkr': {
+                'tist': '42',
+                'tsoll': '32',
+                'absenk': '32',
+                'komfort': '38',
+                'lock': '1',
+                'devicelock': '1',
+                'errorcode': '0',
+                'batterylow': '0',
+                'nextchange': {
+                    'endperiod': '1704888000',
+                    'tchange': '32'
                 }
             }
         }
 
-        energy = int(__switch_01["powermeter"]["energy"])
-        power = int(__switch_01["powermeter"]["power"])
-        start_time = 1703883617
-        energy_up = int(time.time() - start_time) / 3600 * (int(power) / 1000)
-        __switch_01["powermeter"]["energy"] = str(int(energy + energy_up))
-
         # devices.append(__switch_01)
         # devices.append(__repeater_01)
         # devices.append(__repeater_02)
         # devices.append(__thermostat_01)
 
-    for xml_device in xml_devicelist.findall('device'):
+    for xml_device in xml_device_list.findall('device'):
         devices.append(parse_xml_to_json(xml_device))
 
     if args.no_piggyback:
-        sys.stdout.write('<<<fritzbox_smarthome:sep(0)>>>\n')
-        # if len(devices) == 1:
-        #     sys.stdout.write(json.dumps(devices[0]))  # single device
-        # else:
-        sys.stdout.write(json.dumps(devices))
-        sys.stdout.write('\n')
+        stdout.write('<<<fritzbox_smarthome:sep(0)>>>\n')
+        stdout.write(dumps(devices))
+        stdout.write('\n')
     else:
         for json_device in devices:
-            name = json_device["name"].replace(' ', '_')
+            name = json_device['name'].replace(' ', '_')
             name = re_sub(r'[^.\-_a-zA-Z0-9]', '', name)
             if args.prefix:
                 name = f'{args.prefix}-{name}'
-            sys.stdout.write(f'<<<<{name}>>>>\n')
-            sys.stdout.write('<<<fritzbox_smarthome:sep(0)>>>\n')
-            sys.stdout.write(json.dumps(json_device))
-            sys.stdout.write('\n')
+            stdout.write(f'<<<<{name}>>>>\n')
+            stdout.write('<<<fritzbox_smarthome:sep(0)>>>\n')
+            stdout.write(dumps(json_device))
+            stdout.write('\n')
+
+    # logout (invalidate the session-id)
+    avm_session.logout()
 
 
 def main():
     replace_passwords()
     args = parse_args()
-    try:
-        check_fritzbox_smarthome(args)
-    except:
-        if args.debug:
-            raise
-        sys.stderr.write('fritzbox_smarthome\n %s\n' % traceback.format_exc())
-        sys.exit(2)
+    check_fritzbox_smarthome(args)
diff --git a/source/packages/fritzbox_smarthome b/source/packages/fritzbox_smarthome
index ddd982d..5c03fcf 100644
--- a/source/packages/fritzbox_smarthome
+++ b/source/packages/fritzbox_smarthome
@@ -10,18 +10,14 @@
                 'devices, I have only implemented the checks for the following '
                 'devices:\n'
                 '\n'
-                'FRITZ!DECT Repeater 100\n'
-                'FRITZ!DECT 200\n'
-                'FRITZ!DECT 302\n'
+                ' - FRITZ!DECT Repeater 100\n'
+                ' - FRITZ!DECT 200/210\n'
+                ' - FRITZ!DECT 301/302\n'
+                ' - FRITZ!DECT 440\n'
                 '\n'
                 'So if you want the package to be extended to support your '
                 'sensors as well, see\n'
                 'https://thl-cmk.hopto.org/gitlab/checkmk/various/fritzbox_smarthome/-/blob/master/CONTRIBUTING.md\n'
-                '\n'
-                'Also, my FRIT!BOX is not brand new, so it may not include all '
-                'the features that the smart home \n'
-                'devices support.  E.g. window open/close for the FRITZ!DECT '
-                '302.\n'
                 '\n',
  'download_url': 'https://thl-cmk.hopto.org/gitlab/checkmk/various/fritzbox_smarthome',
  'files': {'agent_based': ['fritzbox_smarthome.py',
@@ -34,7 +30,9 @@
                            'fritzbox_smarthome_app_lock.py',
                            'fritzbox_smarthome_device_lock.py',
                            'fritzbox_smarthome_power_socket.py',
-                           'fritzbox_smarthome_switch.py'],
+                           'fritzbox_smarthome_switch.py',
+                           'fritzbox_smarthome_button.py',
+                           'fritzbox_smarthome_humidity.py'],
            'agents': ['special/agent_fritzbox_smarthome'],
            'checkman': ['fritzbox_smarthome'],
            'checks': ['agent_fritzbox_smarthome'],
@@ -45,13 +43,18 @@
                    'wato/check_parameters/temperature_single.py',
                    'wato/check_parameters/voltage_single.py',
                    'wato/check_parameters/fritzbox_smarthome_lock.py',
-                   'wato/check_parameters/fritzbox_smarthome_power_coscket.py'],
+                   'wato/check_parameters/fritzbox_smarthome_power_coscket.py',
+                   'dashboard/avm',
+                   'views/avm_fritzbox',
+                   'views/avm_smart_home_devices_metrics',
+                   'views/avm_smart_home_devices_status',
+                   'views/invavmsmarthomedevices_filtered'],
            'lib': ['python3/cmk/special_agents/agent_fritzbox_smarthome.py'],
            'web': ['plugins/wato/agent_fritzbox_smarthome.py',
                    'plugins/views/fritzbox_smarthome.py']},
  'name': 'fritzbox_smarthome',
  'title': 'Fritz!Box SmartHome',
- 'version': '0.8.8-20240109',
+ 'version': '0.8.17-20240125',
  'version.min_required': '2.2.0b1',
  'version.packaged': '2.2.0p17',
  'version.usable_until': '2.3.0b1'}
diff --git a/source/web/plugins/views/fritzbox_smarthome.py b/source/web/plugins/views/fritzbox_smarthome.py
index 76733ec..d8dfda8 100644
--- a/source/web/plugins/views/fritzbox_smarthome.py
+++ b/source/web/plugins/views/fritzbox_smarthome.py
@@ -34,7 +34,7 @@ inventory_displayhints.update({
     '.hardware.avm.smart_home_devices:*.name': {'title': _l('Name')},
     '.hardware.avm.smart_home_devices:*.manufacturer': {'title': _l('Manufacturer')},
     '.hardware.avm.smart_home_devices:*.product_name': {'title': _l('Product name')},
-    '.hardware.avm.smart_home_devices:*.fw_version': {'title': _l('Firmware version')},
+    '.hardware.avm.smart_home_devices:*.fw_version': {'title': _l('Firmware version'), 'short': _l('Firmware')},
     '.hardware.avm.smart_home_devices:*.identifier': {'title': _l('Identifier')},
     '.hardware.avm.smart_home_devices:*.functions': {'title': _l('Functions')},
 })
diff --git a/source/web/plugins/wato/agent_fritzbox_smarthome.py b/source/web/plugins/wato/agent_fritzbox_smarthome.py
index cc2f867..205dae0 100644
--- a/source/web/plugins/wato/agent_fritzbox_smarthome.py
+++ b/source/web/plugins/wato/agent_fritzbox_smarthome.py
@@ -72,6 +72,13 @@ def _valuespec_special_agents_fritzbox_smarthome() -> ValueSpec:
                 totext='',
                 title=_('Disable piggyback'),
             )),
+            ('no_pbkdf2', FixedValue(
+                value=True,
+                help='The login will fallback from PBDKF2 (Password-Based Key Derivation Function 2) to MD5 '
+                     '(less secure) challenge response method',
+                totext='',
+                title=_('Disable PBDKF2'),
+            )),
             ('testing', FixedValue(
                 value=True,
                 help='Development only, will be (most likely) ignored in production :-)',
-- 
GitLab