Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,12 @@ repos:
rev: v2.2.1
hooks:
- id: prettier
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.19.1
hooks:
- id: mypy
args: []
additional_dependencies:
- cryptography
- types-requests
files: ^pyfritzhome/.+\.py$
67 changes: 36 additions & 31 deletions pyfritzhome/cli.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
#!/usr/bin/env python
"""A simple CLI tool."""

from __future__ import annotations

from __future__ import print_function
from collections.abc import Sequence
import logging
import argparse


from pyfritzhome import Fritzhome, __version__

_LOGGER = logging.getLogger(__name__)


def list_all(fritz, args):
def list_all(fritz: Fritzhome, args: argparse.Namespace) -> None:
"""Command that prints all device information."""
devices = fritz.get_devices()

Expand Down Expand Up @@ -77,73 +79,75 @@ def list_all(fritz, args):
print(" endpositionset=%s" % device.endpositionsset)


def device_name(fritz, args):
def device_name(fritz: Fritzhome, args: argparse.Namespace) -> None:
"""Command that prints the device name."""
print(fritz.get_device_name(args.ain))


def device_presence(fritz, args):
def device_presence(fritz: Fritzhome, args: argparse.Namespace) -> None:
"""Command that prints the device presence."""
print(int(fritz.get_device_present(args.ain)))


def device_statistics(fritz, args):
def device_statistics(fritz: Fritzhome, args: argparse.Namespace) -> None:
"""Command that prints the device statistics."""
stats = fritz.get_device_statistics(args.ain)
print(stats)


def blind_set_open(fritz, args):
def blind_set_open(fritz: Fritzhome, args: argparse.Namespace) -> None:
"""Command to open the blinds."""
fritz.set_blind_open(args.ain)


def blind_set_close(fritz, args):
def blind_set_close(fritz: Fritzhome, args: argparse.Namespace) -> None:
"""Command close the blinds."""
fritz.set_blind_close(args.ain)


def blind_set_level_percentage(fritz, args):
def blind_set_level_percentage(fritz: Fritzhome, args: argparse.Namespace) -> None:
"""Command that sets the blind level as percentage."""
fritz.set_level_percentage(args.ain, args.level)


def thermostat_set_target_temperature(fritz, args):
def thermostat_set_target_temperature(
fritz: Fritzhome, args: argparse.Namespace
) -> None:
"""Command that sets the thermostat temperature."""
fritz.set_target_temperature(args.ain, args.temperature)


def thermostat_set_window_open(fritz, args):
def thermostat_set_window_open(fritz: Fritzhome, args: argparse.Namespace) -> None:
"""Command that sets the thermostats window state."""
fritz.set_window_open(args.ain, args.timespan)


def thermostat_set_boost_mode(fritz, args):
def thermostat_set_boost_mode(fritz: Fritzhome, args: argparse.Namespace) -> None:
"""Command that sets the thermostats into boost mode."""
fritz.set_boost_mode(args.ain, args.timespan)


def switch_get(fritz, args):
def switch_get(fritz: Fritzhome, args: argparse.Namespace) -> None:
"""Command that get the device switch state."""
print(fritz.get_switch_state(args.ain))


def switch_on(fritz, args):
def switch_on(fritz: Fritzhome, args: argparse.Namespace) -> None:
"""Command that set the device switch state to on."""
fritz.set_switch_state_on(args.ain)


def switch_off(fritz, args):
def switch_off(fritz: Fritzhome, args: argparse.Namespace) -> None:
"""Command that set the device switch state to off."""
fritz.set_switch_state_off(args.ain)


def switch_toggle(fritz, args):
def switch_toggle(fritz: Fritzhome, args: argparse.Namespace) -> None:
"""Command that toggles the device switch state."""
fritz.set_switch_state_toggle(args.ain)


def list_templates(fritz, args):
def list_templates(fritz: Fritzhome, args: argparse.Namespace) -> None:
"""Command that prints all template information."""
templates = fritz.get_templates()
devices = fritz.get_devices_as_dict()
Expand All @@ -165,16 +169,17 @@ def list_templates(fritz, args):
print(" dialhelper=%s" % template.apply_dialhelper)

print(" Devices:")
for device_id in template.devices:
print(" %s=%s" % (device_id, devices[device_id].name))
if template.devices is not None:
for device_id in template.devices:
print(" %s=%s" % (device_id, devices[device_id].name))


def template_apply(fritz, args):
def template_apply(fritz: Fritzhome, args: argparse.Namespace) -> None:
"""Command that applies a template."""
fritz.apply_template(args.ain)


def list_triggers(fritz, args):
def list_triggers(fritz: Fritzhome, args: argparse.Namespace) -> None:
"""Command that prints all trigger information."""
triggers = fritz.get_triggers()

Expand All @@ -185,17 +190,17 @@ def list_triggers(fritz, args):
print(" active=%s" % trigger.active)


def trigger_set_active(fritz, args):
def trigger_set_active(fritz: Fritzhome, args: argparse.Namespace) -> None:
"""Command that enables a trigger."""
fritz.set_trigger_active(args.ain)


def trigger_set_inactive(fritz, args):
def trigger_set_inactive(fritz: Fritzhome, args: argparse.Namespace) -> None:
"""Command that disables a trigger."""
fritz.set_trigger_inactive(args.ain)


def main(args=None):
def main(args: Sequence[str] | None = None) -> None:
"""Enter the main function of the CLI tool."""
parser = argparse.ArgumentParser(description="Fritz!Box Smarthome CLI tool.")
parser.add_argument(
Expand Down Expand Up @@ -384,23 +389,23 @@ def main(args=None):
subparser.add_argument("ain", type=str, metavar="AIN", help="Actor Identification")
subparser.set_defaults(func=trigger_set_inactive)

args = parser.parse_args(args)
parsed_args = parser.parse_args(args)

logging.basicConfig()
if args.verbose:
if parsed_args.verbose:
logging.getLogger("pyfritzhome").setLevel(logging.DEBUG)

fritzbox = None
try:
fritzbox = Fritzhome(
host=args.host,
user=args.user,
password=args.password,
port=args.port or None,
ssl_verify=not args.insecure,
host=parsed_args.host,
user=parsed_args.user,
password=parsed_args.password,
port=parsed_args.port or None,
ssl_verify=not parsed_args.insecure,
)
fritzbox.login()
args.func(fritzbox, args)
parsed_args.func(fritzbox, parsed_args)
finally:
if fritzbox is not None:
fritzbox.logout()
Expand Down
12 changes: 8 additions & 4 deletions pyfritzhome/devicetypes/fritzhomedevicealarm.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
"""The alarm device class."""

from __future__ import annotations

import logging

from xml.etree import ElementTree

from .fritzhomedevicebase import FritzhomeDeviceBase
from .fritzhomedevicefeatures import FritzhomeDeviceFeatures

Expand All @@ -11,9 +15,9 @@
class FritzhomeDeviceAlarm(FritzhomeDeviceBase):
"""The Fritzhome Device class."""

alert_state = None
alert_state: bool | None = None

def _update_from_node(self, node):
def _update_from_node(self, node: ElementTree.Element) -> None:
super()._update_from_node(node)
if self.present is False:
return
Expand All @@ -23,11 +27,11 @@ def _update_from_node(self, node):

# Alarm
@property
def has_alarm(self):
def has_alarm(self) -> bool:
"""Check if the device has alarm function."""
return self._has_feature(FritzhomeDeviceFeatures.ALARM)

def _update_alarm_from_node(self, node):
def _update_alarm_from_node(self, node: ElementTree.Element) -> None:
_LOGGER.debug("update alert device")
val = node.find("alert")
try:
Expand Down
42 changes: 23 additions & 19 deletions pyfritzhome/devicetypes/fritzhomedevicebase.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
"""The base device class."""

from __future__ import print_function

from __future__ import annotations

import logging

from xml.etree import ElementTree

from pyfritzhome.devicetypes.fritzhomeentitybase import FritzhomeEntityBase

_LOGGER = logging.getLogger(__name__)
Expand All @@ -13,18 +14,18 @@
class FritzhomeDeviceBase(FritzhomeEntityBase):
"""The Fritzhome Device class."""

battery_level = None
battery_low = None
identifier = None
is_group = None
fw_version = None
group_members = None
manufacturer = None
productname = None
present = None
tx_busy = None

def __repr__(self):
battery_level: int | None = None
battery_low: bool | None = None
identifier: str | None = None
is_group: bool | None = None
fw_version: str | None = None
group_members: list[str] | None = None
manufacturer: str | None = None
productname: str | None = None
present: bool | None = None
tx_busy: bool | None = None

def __repr__(self) -> str:
"""Return a string."""
return "{ain} {identifier} {manuf} {prod} {name}".format(
ain=self.ain,
Expand All @@ -34,11 +35,11 @@ def __repr__(self):
name=self.name,
)

def update(self):
def update(self) -> None:
"""Update the device values."""
self._fritz.update_devices()

def _update_from_node(self, node):
def _update_from_node(self, node: ElementTree.Element) -> None:
_LOGGER.debug("update base device")
super()._update_from_node(node)
self.ain = node.attrib["identifier"]
Expand All @@ -47,11 +48,14 @@ def _update_from_node(self, node):
self.manufacturer = node.attrib["manufacturer"]
self.productname = node.attrib["productname"]

self.present = bool(int(node.findtext("present")))
present_value = node.findtext("present")
if present_value is None:
raise ValueError("device node is missing present state")
self.present = bool(int(present_value))

groupinfo = node.find("groupinfo")
self.is_group = groupinfo is not None
if self.is_group:
if groupinfo is not None:
Comment thread
mib1185 marked this conversation as resolved.
self.group_members = str(groupinfo.findtext("members")).split(",")

try:
Expand All @@ -66,6 +70,6 @@ def _update_from_node(self, node):
pass

# General
def get_present(self):
def get_present(self) -> bool:
"""Check if the device is present."""
return self._fritz.get_device_present(self.ain)
18 changes: 11 additions & 7 deletions pyfritzhome/devicetypes/fritzhomedeviceblind.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
"""The blind device class."""

from __future__ import annotations

import logging

from xml.etree import ElementTree

from .fritzhomedevicebase import FritzhomeDeviceBase
from .fritzhomedevicefeatures import FritzhomeDeviceFeatures

Expand All @@ -11,9 +15,9 @@
class FritzhomeDeviceBlind(FritzhomeDeviceBase):
"""The Fritzhome Device class."""

endpositionsset = None
endpositionsset: bool | None = None

def _update_from_node(self, node):
def _update_from_node(self, node: ElementTree.Element) -> None:
super()._update_from_node(node)
if self.present is False:
return
Expand All @@ -23,11 +27,11 @@ def _update_from_node(self, node):

# Blind
@property
def has_blind(self):
def has_blind(self) -> bool:
"""Check if the device has blind function."""
return self._has_feature(FritzhomeDeviceFeatures.BLIND)

def _update_blind_from_node(self, node):
def _update_blind_from_node(self, node: ElementTree.Element) -> None:
_LOGGER.debug("update blind device")
blind_element = node.find("blind")
try:
Expand All @@ -37,14 +41,14 @@ def _update_blind_from_node(self, node):
except Exception:
pass

def set_blind_open(self, wait=False):
def set_blind_open(self, wait: bool = False) -> None:
"""Open the blind."""
self._fritz.set_blind_open(self.ain, wait)

def set_blind_close(self, wait=False):
def set_blind_close(self, wait: bool = False) -> None:
"""Close the blind."""
self._fritz.set_blind_close(self.ain, wait)

def set_blind_stop(self, wait=False):
def set_blind_stop(self, wait: bool = False) -> None:
"""Stop the blind."""
self._fritz.set_blind_stop(self.ain, wait)
Loading
Loading