Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add some more typing to HomeKit #101959

Merged
merged 1 commit into from
Oct 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
58 changes: 31 additions & 27 deletions homeassistant/components/homekit/type_media_players.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import logging
from typing import Any

from pyhap.characteristic import Characteristic
from pyhap.const import CATEGORY_SWITCH

from homeassistant.components.media_player import (
Expand Down Expand Up @@ -32,7 +33,7 @@
STATE_STANDBY,
STATE_UNKNOWN,
)
from homeassistant.core import callback
from homeassistant.core import State, callback

from .accessories import TYPES, HomeAccessory
from .const import (
Expand Down Expand Up @@ -82,11 +83,12 @@
class MediaPlayer(HomeAccessory):
"""Generate a Media Player accessory."""

def __init__(self, *args):
def __init__(self, *args: Any) -> None:
"""Initialize a Switch accessory object."""
super().__init__(*args, category=CATEGORY_SWITCH)
state = self.hass.states.get(self.entity_id)
self.chars = {
assert state
self.chars: dict[str, Characteristic | None] = {
FEATURE_ON_OFF: None,
FEATURE_PLAY_PAUSE: None,
FEATURE_PLAY_STOP: None,
Expand Down Expand Up @@ -137,20 +139,20 @@ def __init__(self, *args):
)
self.async_update_state(state)

def generate_service_name(self, mode):
def generate_service_name(self, mode: str) -> str:
"""Generate name for individual service."""
return cleanup_name_for_homekit(
f"{self.display_name} {MODE_FRIENDLY_NAME[mode]}"
)

def set_on_off(self, value):
def set_on_off(self, value: bool) -> None:
"""Move switch state to value if call came from HomeKit."""
_LOGGER.debug('%s: Set switch state for "on_off" to %s', self.entity_id, value)
service = SERVICE_TURN_ON if value else SERVICE_TURN_OFF
params = {ATTR_ENTITY_ID: self.entity_id}
self.async_call_service(DOMAIN, service, params)

def set_play_pause(self, value):
def set_play_pause(self, value: bool) -> None:
"""Move switch state to value if call came from HomeKit."""
_LOGGER.debug(
'%s: Set switch state for "play_pause" to %s', self.entity_id, value
Expand All @@ -159,7 +161,7 @@ def set_play_pause(self, value):
params = {ATTR_ENTITY_ID: self.entity_id}
self.async_call_service(DOMAIN, service, params)

def set_play_stop(self, value):
def set_play_stop(self, value: bool) -> None:
"""Move switch state to value if call came from HomeKit."""
_LOGGER.debug(
'%s: Set switch state for "play_stop" to %s', self.entity_id, value
Expand All @@ -168,7 +170,7 @@ def set_play_stop(self, value):
params = {ATTR_ENTITY_ID: self.entity_id}
self.async_call_service(DOMAIN, service, params)

def set_toggle_mute(self, value):
def set_toggle_mute(self, value: bool) -> None:
"""Move switch state to value if call came from HomeKit."""
_LOGGER.debug(
'%s: Set switch state for "toggle_mute" to %s', self.entity_id, value
Expand All @@ -177,43 +179,43 @@ def set_toggle_mute(self, value):
self.async_call_service(DOMAIN, SERVICE_VOLUME_MUTE, params)

@callback
def async_update_state(self, new_state):
def async_update_state(self, new_state: State) -> None:
"""Update switch state after state changed."""
current_state = new_state.state

if self.chars[FEATURE_ON_OFF]:
if on_off_char := self.chars[FEATURE_ON_OFF]:
hk_state = current_state not in MEDIA_PLAYER_OFF_STATES
_LOGGER.debug(
'%s: Set current state for "on_off" to %s', self.entity_id, hk_state
)
self.chars[FEATURE_ON_OFF].set_value(hk_state)
on_off_char.set_value(hk_state)

if self.chars[FEATURE_PLAY_PAUSE]:
if play_pause_char := self.chars[FEATURE_PLAY_PAUSE]:
hk_state = current_state == STATE_PLAYING
_LOGGER.debug(
'%s: Set current state for "play_pause" to %s',
self.entity_id,
hk_state,
)
self.chars[FEATURE_PLAY_PAUSE].set_value(hk_state)
play_pause_char.set_value(hk_state)

if self.chars[FEATURE_PLAY_STOP]:
if play_stop_char := self.chars[FEATURE_PLAY_STOP]:
hk_state = current_state == STATE_PLAYING
_LOGGER.debug(
'%s: Set current state for "play_stop" to %s',
self.entity_id,
hk_state,
)
self.chars[FEATURE_PLAY_STOP].set_value(hk_state)
play_stop_char.set_value(hk_state)

if self.chars[FEATURE_TOGGLE_MUTE]:
current_state = bool(new_state.attributes.get(ATTR_MEDIA_VOLUME_MUTED))
if toggle_mute_char := self.chars[FEATURE_TOGGLE_MUTE]:
mute_state = bool(new_state.attributes.get(ATTR_MEDIA_VOLUME_MUTED))
_LOGGER.debug(
'%s: Set current state for "toggle_mute" to %s',
self.entity_id,
current_state,
mute_state,
)
self.chars[FEATURE_TOGGLE_MUTE].set_value(current_state)
toggle_mute_char.set_value(mute_state)


@TYPES.register("TelevisionMediaPlayer")
Expand Down Expand Up @@ -278,42 +280,42 @@ def __init__(self, *args: Any, **kwargs: Any) -> None:

self.async_update_state(state)

def set_on_off(self, value):
def set_on_off(self, value: bool) -> None:
"""Move switch state to value if call came from HomeKit."""
_LOGGER.debug('%s: Set switch state for "on_off" to %s', self.entity_id, value)
service = SERVICE_TURN_ON if value else SERVICE_TURN_OFF
params = {ATTR_ENTITY_ID: self.entity_id}
self.async_call_service(DOMAIN, service, params)

def set_mute(self, value):
def set_mute(self, value: bool) -> None:
"""Move switch state to value if call came from HomeKit."""
_LOGGER.debug(
'%s: Set switch state for "toggle_mute" to %s', self.entity_id, value
)
params = {ATTR_ENTITY_ID: self.entity_id, ATTR_MEDIA_VOLUME_MUTED: value}
self.async_call_service(DOMAIN, SERVICE_VOLUME_MUTE, params)

def set_volume(self, value):
def set_volume(self, value: bool) -> None:
"""Send volume step value if call came from HomeKit."""
_LOGGER.debug("%s: Set volume to %s", self.entity_id, value)
params = {ATTR_ENTITY_ID: self.entity_id, ATTR_MEDIA_VOLUME_LEVEL: value}
self.async_call_service(DOMAIN, SERVICE_VOLUME_SET, params)

def set_volume_step(self, value):
def set_volume_step(self, value: bool) -> None:
"""Send volume step value if call came from HomeKit."""
_LOGGER.debug("%s: Step volume by %s", self.entity_id, value)
service = SERVICE_VOLUME_DOWN if value else SERVICE_VOLUME_UP
params = {ATTR_ENTITY_ID: self.entity_id}
self.async_call_service(DOMAIN, service, params)

def set_input_source(self, value):
def set_input_source(self, value: int) -> None:
"""Send input set value if call came from HomeKit."""
_LOGGER.debug("%s: Set current input to %s", self.entity_id, value)
source_name = self._mapped_sources[self.sources[value]]
params = {ATTR_ENTITY_ID: self.entity_id, ATTR_INPUT_SOURCE: source_name}
self.async_call_service(DOMAIN, SERVICE_SELECT_SOURCE, params)

def set_remote_key(self, value):
def set_remote_key(self, value: int) -> None:
"""Send remote key value if call came from HomeKit."""
_LOGGER.debug("%s: Set remote key to %s", self.entity_id, value)
if (key_name := REMOTE_KEYS.get(value)) is None:
Expand All @@ -322,7 +324,9 @@ def set_remote_key(self, value):

if key_name == KEY_PLAY_PAUSE and self._supports_play_pause:
# Handle Play Pause by directly updating the media player entity.
state = self.hass.states.get(self.entity_id).state
state_obj = self.hass.states.get(self.entity_id)
assert state_obj
state = state_obj.state
if state in (STATE_PLAYING, STATE_PAUSED):
service = (
SERVICE_MEDIA_PLAY if state == STATE_PAUSED else SERVICE_MEDIA_PAUSE
Expand All @@ -340,7 +344,7 @@ def set_remote_key(self, value):
)

@callback
def async_update_state(self, new_state):
def async_update_state(self, new_state: State) -> None:
"""Update Television state after state changed."""
current_state = new_state.state

Expand Down
14 changes: 8 additions & 6 deletions homeassistant/components/homekit/type_remotes.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,31 +219,33 @@ def _async_update_input_state(self, hk_state, new_state):
class ActivityRemote(RemoteInputSelectAccessory):
"""Generate a Activity Remote accessory."""

def __init__(self, *args):
def __init__(self, *args: Any) -> None:
"""Initialize a Activity Remote accessory object."""
super().__init__(
RemoteEntityFeature.ACTIVITY,
ATTR_CURRENT_ACTIVITY,
ATTR_ACTIVITY_LIST,
*args,
)
self.async_update_state(self.hass.states.get(self.entity_id))
state = self.hass.states.get(self.entity_id)
assert state
self.async_update_state(state)

def set_on_off(self, value):
def set_on_off(self, value: bool) -> None:
"""Move switch state to value if call came from HomeKit."""
_LOGGER.debug('%s: Set switch state for "on_off" to %s', self.entity_id, value)
service = SERVICE_TURN_ON if value else SERVICE_TURN_OFF
params = {ATTR_ENTITY_ID: self.entity_id}
self.async_call_service(REMOTE_DOMAIN, service, params)

def set_input_source(self, value):
def set_input_source(self, value: int) -> None:
"""Send input set value if call came from HomeKit."""
_LOGGER.debug("%s: Set current input to %s", self.entity_id, value)
source = self._mapped_sources[self.sources[value]]
params = {ATTR_ENTITY_ID: self.entity_id, ATTR_ACTIVITY: source}
self.async_call_service(REMOTE_DOMAIN, SERVICE_TURN_ON, params)

def set_remote_key(self, value):
def set_remote_key(self, value: int) -> None:
"""Send remote key value if call came from HomeKit."""
_LOGGER.debug("%s: Set remote key to %s", self.entity_id, value)
if (key_name := REMOTE_KEYS.get(value)) is None:
Expand All @@ -255,7 +257,7 @@ def set_remote_key(self, value):
)

@callback
def async_update_state(self, new_state):
def async_update_state(self, new_state: State) -> None:
"""Update Television remote state after state changed."""
current_state = new_state.state
# Power state remote
Expand Down
10 changes: 6 additions & 4 deletions homeassistant/components/homekit/type_security_systems.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""Class to hold all alarm control panel accessories."""
import logging
from typing import Any

from pyhap.const import CATEGORY_ALARM_SYSTEM

Expand All @@ -23,7 +24,7 @@
STATE_ALARM_DISARMED,
STATE_ALARM_TRIGGERED,
)
from homeassistant.core import callback
from homeassistant.core import State, callback

from .accessories import TYPES, HomeAccessory
from .const import (
Expand Down Expand Up @@ -78,10 +79,11 @@
class SecuritySystem(HomeAccessory):
"""Generate an SecuritySystem accessory for an alarm control panel."""

def __init__(self, *args):
def __init__(self, *args: Any) -> None:
"""Initialize a SecuritySystem accessory object."""
super().__init__(*args, category=CATEGORY_ALARM_SYSTEM)
state = self.hass.states.get(self.entity_id)
assert state
self._alarm_code = self.config.get(ATTR_CODE)

supported_states = state.attributes.get(
Expand Down Expand Up @@ -143,7 +145,7 @@ def __init__(self, *args):
# GET to avoid an event storm after homekit startup
self.async_update_state(state)

def set_security_state(self, value):
def set_security_state(self, value: int) -> None:
"""Move security state to value if call came from HomeKit."""
_LOGGER.debug("%s: Set security state to %d", self.entity_id, value)
service = HK_TO_SERVICE[value]
Expand All @@ -153,7 +155,7 @@ def set_security_state(self, value):
self.async_call_service(DOMAIN, service, params)

@callback
def async_update_state(self, new_state):
def async_update_state(self, new_state: State) -> None:
"""Update security state after state changed."""
hass_state = new_state.state
if (current_state := HASS_TO_HOMEKIT_CURRENT.get(hass_state)) is not None:
Expand Down