Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions homeassistant/components/huawei_lte/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from collections.abc import Callable, Sequence
from dataclasses import dataclass
from datetime import datetime, timedelta
import ipaddress
import logging
import re

Expand Down Expand Up @@ -85,6 +86,17 @@ def format_last_reset_elapsed_seconds(value: str | None) -> datetime | None:
return last_reset


def format_ipv6(value: StateType) -> tuple[StateType, str | None]:
"""Format an IPv6 address for tidy display.

Raw values from the device may contain uppercase and redundant segments.
"""
try:
return str(ipaddress.IPv6Address(str(value))), None
except ValueError:
return value, None


def signal_icon(limits: Sequence[int], value: StateType) -> str:
"""Get signal icon."""
return (
Expand Down Expand Up @@ -139,6 +151,7 @@ class HuaweiSensorEntityDescription(SensorEntityDescription):
key="uptime",
translation_key="uptime",
native_unit_of_measurement=UnitOfTime.SECONDS,
suggested_display_precision=0,
device_class=SensorDeviceClass.DURATION,
entity_category=EntityCategory.DIAGNOSTIC,
),
Expand All @@ -151,6 +164,7 @@ class HuaweiSensorEntityDescription(SensorEntityDescription):
"WanIPv6Address": HuaweiSensorEntityDescription(
key="WanIPv6Address",
translation_key="wan_ipv6_address",
format_fn=format_ipv6,
entity_category=EntityCategory.DIAGNOSTIC,
),
},
Expand Down Expand Up @@ -200,11 +214,13 @@ class HuaweiSensorEntityDescription(SensorEntityDescription):
translation_key="downlink_bandwidth",
# https://en.wikipedia.org/wiki/LTE_frequency_bands, arbitrary
icon_fn=lambda x: bandwidth_icon((8, 15), x),
suggested_display_precision=0,
entity_category=EntityCategory.DIAGNOSTIC,
),
"dlfrequency": HuaweiSensorEntityDescription(
key="dlfrequency",
translation_key="downlink_frequency",
suggested_display_precision=0,
device_class=SensorDeviceClass.FREQUENCY,
entity_category=EntityCategory.DIAGNOSTIC,
),
Expand Down Expand Up @@ -317,6 +333,7 @@ class HuaweiSensorEntityDescription(SensorEntityDescription):
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
# https://wiki.teltonika-networks.com/view/RSRP_and_RSRQ
icon_fn=lambda x: signal_icon((-100, -90, -80), x),
suggested_display_precision=0,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=True,
Expand All @@ -337,6 +354,7 @@ class HuaweiSensorEntityDescription(SensorEntityDescription):
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
# https://wiki.teltonika-networks.com/view/SINR
icon_fn=lambda x: signal_icon((0, 13, 20), x),
suggested_display_precision=0,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=True,
Expand All @@ -360,6 +378,7 @@ class HuaweiSensorEntityDescription(SensorEntityDescription):
translation_key="nrulbandwidth",
# https://en.wikipedia.org/wiki/5G_NR_frequency_bands, arbitrary
icon_fn=lambda x: bandwidth_icon((33, 66), x),
suggested_display_precision=0,
entity_category=EntityCategory.DIAGNOSTIC,
),
"nrulmcs": HuaweiSensorEntityDescription(
Expand Down Expand Up @@ -402,6 +421,7 @@ class HuaweiSensorEntityDescription(SensorEntityDescription):
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
# https://wiki.teltonika-networks.com/view/RSRP_and_RSRQ
icon_fn=lambda x: signal_icon((-100, -90, -80), x),
suggested_display_precision=0,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=True,
Expand All @@ -422,6 +442,7 @@ class HuaweiSensorEntityDescription(SensorEntityDescription):
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
# https://wiki.teltonika-networks.com/view/RSSI
icon_fn=lambda x: signal_icon((-95, -85, -75), x),
suggested_display_precision=0,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=True,
Expand All @@ -443,6 +464,7 @@ class HuaweiSensorEntityDescription(SensorEntityDescription):
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
# https://wiki.teltonika-networks.com/view/SINR
icon_fn=lambda x: signal_icon((0, 13, 20), x),
suggested_display_precision=0,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=True,
Expand Down Expand Up @@ -486,17 +508,20 @@ class HuaweiSensorEntityDescription(SensorEntityDescription):
translation_key="uplink_bandwidth",
# https://en.wikipedia.org/wiki/LTE_frequency_bands, arbitrary
icon_fn=lambda x: bandwidth_icon((8, 15), x),
suggested_display_precision=0,
entity_category=EntityCategory.DIAGNOSTIC,
),
"ulfrequency": HuaweiSensorEntityDescription(
key="ulfrequency",
translation_key="uplink_frequency",
suggested_display_precision=0,
device_class=SensorDeviceClass.FREQUENCY,
entity_category=EntityCategory.DIAGNOSTIC,
),
"wdlfreq": HuaweiSensorEntityDescription(
key="wdlfreq",
translation_key="wdlfreq",
suggested_display_precision=0,
device_class=SensorDeviceClass.FREQUENCY,
entity_category=EntityCategory.DIAGNOSTIC,
),
Expand Down Expand Up @@ -583,6 +608,7 @@ class HuaweiSensorEntityDescription(SensorEntityDescription):
"PrimaryIPv6Dns": HuaweiSensorEntityDescription(
key="PrimaryIPv6Dns",
translation_key="primary_ipv6_dns_server",
format_fn=format_ipv6,
entity_category=EntityCategory.DIAGNOSTIC,
),
"SecondaryDns": HuaweiSensorEntityDescription(
Expand All @@ -593,6 +619,7 @@ class HuaweiSensorEntityDescription(SensorEntityDescription):
"SecondaryIPv6Dns": HuaweiSensorEntityDescription(
key="SecondaryIPv6Dns",
translation_key="secondary_ipv6_dns_server",
format_fn=format_ipv6,
entity_category=EntityCategory.DIAGNOSTIC,
),
},
Expand All @@ -604,6 +631,7 @@ class HuaweiSensorEntityDescription(SensorEntityDescription):
key="CurrentConnectTime",
translation_key="current_connection_duration",
native_unit_of_measurement=UnitOfTime.SECONDS,
suggested_display_precision=0,
device_class=SensorDeviceClass.DURATION,
),
"CurrentDownload": HuaweiSensorEntityDescription(
Expand Down Expand Up @@ -652,6 +680,7 @@ class HuaweiSensorEntityDescription(SensorEntityDescription):
key="TotalConnectTime",
translation_key="total_connected_duration",
native_unit_of_measurement=UnitOfTime.SECONDS,
suggested_display_precision=0,
device_class=SensorDeviceClass.DURATION,
state_class=SensorStateClass.TOTAL_INCREASING,
),
Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/mpd/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"codeowners": [],
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/mpd",
"integration_type": "device",
"iot_class": "local_polling",
"loggers": ["mpd"],
"requirements": ["python-mpd2==3.1.1"]
Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/mutesync/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"codeowners": ["@currentoor"],
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/mutesync",
"integration_type": "service",
"iot_class": "local_polling",
"loggers": ["mutesync"],
"requirements": ["mutesync==0.0.1"]
Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/mystrom/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"config_flow": true,
"dependencies": ["http"],
"documentation": "https://www.home-assistant.io/integrations/mystrom",
"integration_type": "device",
"iot_class": "local_polling",
"loggers": ["pymystrom"],
"requirements": ["python-mystrom==2.5.0"]
Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/nanoleaf/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"homekit": {
"models": ["NL29", "NL42", "NL47", "NL48", "NL52", "NL59", "NL69", "NL81"]
},
"integration_type": "device",
"iot_class": "local_push",
"loggers": ["aionanoleaf"],
"requirements": ["aionanoleaf==0.2.1"],
Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/neato/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"config_flow": true,
"dependencies": ["application_credentials"],
"documentation": "https://www.home-assistant.io/integrations/neato",
"integration_type": "hub",
"iot_class": "cloud_polling",
"loggers": ["pybotvac"],
"requirements": ["pybotvac==0.0.28"]
Expand Down
6 changes: 6 additions & 0 deletions homeassistant/components/switchbot/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,11 @@
Platform.CLIMATE,
Platform.SENSOR,
],
SupportedModels.ART_FRAME.value: [
Platform.SENSOR,
Platform.BINARY_SENSOR,
Platform.BUTTON,
],
}
CLASS_BY_DEVICE = {
SupportedModels.CEILING_LIGHT.value: switchbot.SwitchbotCeilingLight,
Expand Down Expand Up @@ -144,6 +149,7 @@
SupportedModels.RELAY_SWITCH_2PM.value: switchbot.SwitchbotRelaySwitch2PM,
SupportedModels.GARAGE_DOOR_OPENER.value: switchbot.SwitchbotGarageDoorOpener,
SupportedModels.SMART_THERMOSTAT_RADIATOR.value: switchbot.SwitchbotSmartThermostatRadiator,
SupportedModels.ART_FRAME.value: switchbot.SwitchbotArtFrame,
}


Expand Down
6 changes: 6 additions & 0 deletions homeassistant/components/switchbot/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,12 @@ class SwitchbotBinarySensorEntityDescription(BinarySensorEntityDescription):
name=None,
device_class=BinarySensorDeviceClass.MOISTURE,
),
"battery_charging": SwitchbotBinarySensorEntityDescription(
key="battery_charging",
translation_key="battery_charging",
entity_category=EntityCategory.DIAGNOSTIC,
device_class=BinarySensorDeviceClass.BATTERY_CHARGING,
),
}


Expand Down
66 changes: 66 additions & 0 deletions homeassistant/components/switchbot/button.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
"""Button support for SwitchBot devices."""

import logging

import switchbot

from homeassistant.components.button import ButtonEntity
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback

from .coordinator import SwitchbotConfigEntry, SwitchbotDataUpdateCoordinator
from .entity import SwitchbotEntity, exception_handler

_LOGGER = logging.getLogger(__name__)
PARALLEL_UPDATES = 0


async def async_setup_entry(
hass: HomeAssistant,
entry: SwitchbotConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up Switchbot button platform."""
coordinator = entry.runtime_data

if isinstance(coordinator.device, switchbot.SwitchbotArtFrame):
async_add_entities(
[
SwitchBotArtFrameNextButton(coordinator, "next_image"),
SwitchBotArtFramePrevButton(coordinator, "previous_image"),
]
)


class SwitchBotArtFrameButtonBase(SwitchbotEntity, ButtonEntity):
"""Base class for Art Frame buttons."""

_device: switchbot.SwitchbotArtFrame

def __init__(
self, coordinator: SwitchbotDataUpdateCoordinator, translation_key: str
) -> None:
"""Initialize the button base."""
super().__init__(coordinator)
self._attr_unique_id = f"{coordinator.base_unique_id}_{translation_key}"
self._attr_translation_key = translation_key


class SwitchBotArtFrameNextButton(SwitchBotArtFrameButtonBase):
"""Representation of a next image button."""

@exception_handler
async def async_press(self) -> None:
"""Handle the button press."""
_LOGGER.debug("Pressing next image button %s", self._address)
await self._device.next_image()


class SwitchBotArtFramePrevButton(SwitchBotArtFrameButtonBase):
"""Representation of a previous image button."""

@exception_handler
async def async_press(self) -> None:
"""Handle the button press."""
_LOGGER.debug("Pressing previous image button %s", self._address)
await self._device.prev_image()
4 changes: 4 additions & 0 deletions homeassistant/components/switchbot/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ class SupportedModels(StrEnum):
CLIMATE_PANEL = "climate_panel"
SMART_THERMOSTAT_RADIATOR = "smart_thermostat_radiator"
S20_VACUUM = "s20_vacuum"
ART_FRAME = "art_frame"


CONNECTABLE_SUPPORTED_MODEL_TYPES = {
Expand Down Expand Up @@ -100,6 +101,7 @@ class SupportedModels(StrEnum):
SwitchbotModel.GARAGE_DOOR_OPENER: SupportedModels.GARAGE_DOOR_OPENER,
SwitchbotModel.CLIMATE_PANEL: SupportedModels.CLIMATE_PANEL,
SwitchbotModel.SMART_THERMOSTAT_RADIATOR: SupportedModels.SMART_THERMOSTAT_RADIATOR,
SwitchbotModel.ART_FRAME: SupportedModels.ART_FRAME,
}

NON_CONNECTABLE_SUPPORTED_MODEL_TYPES = {
Expand Down Expand Up @@ -139,6 +141,7 @@ class SupportedModels(StrEnum):
SwitchbotModel.RELAY_SWITCH_2PM,
SwitchbotModel.GARAGE_DOOR_OPENER,
SwitchbotModel.SMART_THERMOSTAT_RADIATOR,
SwitchbotModel.ART_FRAME,
}

ENCRYPTED_SWITCHBOT_MODEL_TO_CLASS: dict[
Expand All @@ -161,6 +164,7 @@ class SupportedModels(StrEnum):
SwitchbotModel.RELAY_SWITCH_2PM: switchbot.SwitchbotRelaySwitch2PM,
SwitchbotModel.GARAGE_DOOR_OPENER: switchbot.SwitchbotRelaySwitch,
SwitchbotModel.SMART_THERMOSTAT_RADIATOR: switchbot.SwitchbotSmartThermostatRadiator,
SwitchbotModel.ART_FRAME: switchbot.SwitchbotArtFrame,
}

HASS_SENSOR_TYPE_TO_SWITCHBOT_MODEL = {
Expand Down
8 changes: 8 additions & 0 deletions homeassistant/components/switchbot/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,14 @@
"name": "Unlocked alarm"
}
},
"button": {
"next_image": {
"name": "Next image"
},
"previous_image": {
"name": "Previous image"
}
},
"climate": {
"climate": {
"state_attributes": {
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/tuya/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,5 @@
"integration_type": "hub",
"iot_class": "cloud_push",
"loggers": ["tuya_sharing"],
"requirements": ["tuya-device-sharing-sdk==0.2.6"]
"requirements": ["tuya-device-sharing-sdk==0.2.7"]
}
8 changes: 4 additions & 4 deletions homeassistant/generated/integrations.json
Original file line number Diff line number Diff line change
Expand Up @@ -4217,7 +4217,7 @@
},
"mpd": {
"name": "Music Player Daemon (MPD)",
"integration_type": "hub",
"integration_type": "device",
"config_flow": true,
"iot_class": "local_polling"
},
Expand Down Expand Up @@ -4277,7 +4277,7 @@
},
"mutesync": {
"name": "mutesync",
"integration_type": "hub",
"integration_type": "service",
"config_flow": true,
"iot_class": "local_polling"
},
Expand All @@ -4301,7 +4301,7 @@
},
"mystrom": {
"name": "myStrom",
"integration_type": "hub",
"integration_type": "device",
"config_flow": true,
"iot_class": "local_polling"
},
Expand Down Expand Up @@ -4337,7 +4337,7 @@
},
"nanoleaf": {
"name": "Nanoleaf",
"integration_type": "hub",
"integration_type": "device",
"config_flow": true,
"iot_class": "local_push"
},
Expand Down
2 changes: 1 addition & 1 deletion requirements_all.txt

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading