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
4 changes: 2 additions & 2 deletions CODEOWNERS

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

2 changes: 1 addition & 1 deletion homeassistant/components/aquacell/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def __init__(
self._attr_unique_id = f"{softener_key}-{entity_key}"
self._attr_device_info = DeviceInfo(
name=self.softener.name,
hw_version=self.softener.fwVersion,
hw_version=self.softener.diagnostics.fw_version,
identifiers={(DOMAIN, str(softener_key))},
manufacturer=self.softener.brand,
model=self.softener.ssn,
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/aquacell/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@
"integration_type": "device",
"iot_class": "cloud_polling",
"loggers": ["aioaquacell"],
"requirements": ["aioaquacell==0.2.0"]
"requirements": ["aioaquacell==1.0.0"]
}
14 changes: 7 additions & 7 deletions homeassistant/components/aquacell/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,39 +38,39 @@ class SoftenerSensorEntityDescription(SensorEntityDescription):
translation_key="salt_left_side_percentage",
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=PERCENTAGE,
value_fn=lambda softener: softener.salt.leftPercent,
value_fn=lambda softener: softener.salt.left_percent,
),
SoftenerSensorEntityDescription(
key="salt_right_side_percentage",
translation_key="salt_right_side_percentage",
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=PERCENTAGE,
value_fn=lambda softener: softener.salt.rightPercent,
value_fn=lambda softener: softener.salt.right_percent,
),
SoftenerSensorEntityDescription(
key="salt_left_side_time_remaining",
translation_key="salt_left_side_time_remaining",
device_class=SensorDeviceClass.DURATION,
native_unit_of_measurement=UnitOfTime.DAYS,
value_fn=lambda softener: softener.salt.leftDays,
value_fn=lambda softener: softener.salt.left_days,
),
SoftenerSensorEntityDescription(
key="salt_right_side_time_remaining",
translation_key="salt_right_side_time_remaining",
device_class=SensorDeviceClass.DURATION,
native_unit_of_measurement=UnitOfTime.DAYS,
value_fn=lambda softener: softener.salt.rightDays,
value_fn=lambda softener: softener.salt.right_days,
),
SoftenerSensorEntityDescription(
key="battery",
device_class=SensorDeviceClass.BATTERY,
native_unit_of_measurement=PERCENTAGE,
value_fn=lambda softener: softener.battery,
value_fn=lambda softener: softener.diagnostics.battery,
),
SoftenerSensorEntityDescription(
key="wi_fi_strength",
translation_key="wi_fi_strength",
value_fn=lambda softener: softener.wifiLevel,
value_fn=lambda softener: softener.diagnostics.wifi_level,
device_class=SensorDeviceClass.ENUM,
options=[
"high",
Expand All @@ -82,7 +82,7 @@ class SoftenerSensorEntityDescription(SensorEntityDescription):
key="last_update",
translation_key="last_update",
device_class=SensorDeviceClass.TIMESTAMP,
value_fn=lambda softener: softener.lastUpdate,
value_fn=lambda softener: softener.diagnostics.last_update,
),
)

Expand Down
3 changes: 2 additions & 1 deletion homeassistant/components/duco/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@
async def async_setup_entry(hass: HomeAssistant, entry: DucoConfigEntry) -> bool:
"""Set up Duco from a config entry."""
client = DucoClient(
session=async_get_clientsession(hass),
session=async_get_clientsession(hass, verify_ssl=False),
host=entry.data[CONF_HOST],
scheme="https",
)

coordinator = DucoCoordinator(hass, entry, client)
Expand Down
3 changes: 2 additions & 1 deletion homeassistant/components/duco/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,9 @@ async def _validate_input(self, host: str) -> tuple[str, str]:
Returns a tuple of (box_name, mac_address).
"""
client = DucoClient(
session=async_get_clientsession(self.hass),
session=async_get_clientsession(self.hass, verify_ssl=False),
host=host,
scheme="https",
)
board_info = await client.async_get_board_info()
lan_info = await client.async_get_lan_info()
Expand Down
20 changes: 20 additions & 0 deletions homeassistant/components/duco/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
PERCENTAGE,
SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
EntityCategory,
UnitOfTemperature,
)
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import device_registry as dr
Expand Down Expand Up @@ -59,6 +60,25 @@ class DucoBoxSensorEntityDescription(SensorEntityDescription):
),
node_types=(NodeType.BOX,),
),
DucoSensorEntityDescription(
key="temperature",
device_class=SensorDeviceClass.TEMPERATURE,
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
value_fn=lambda node: node.sensor.temp if node.sensor else None,
node_types=(NodeType.UCCO2, NodeType.BSRH, NodeType.UCRH),
),
DucoSensorEntityDescription(
key="box_temperature",
translation_key="box_temperature",
device_class=SensorDeviceClass.TEMPERATURE,
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
value_fn=lambda node: node.sensor.temp if node.sensor else None,
node_types=(NodeType.BOX,),
),
DucoSensorEntityDescription(
key="co2",
device_class=SensorDeviceClass.CO2,
Expand Down
3 changes: 3 additions & 0 deletions homeassistant/components/duco/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@
}
},
"sensor": {
"box_temperature": {
"name": "Box temperature"
},
"iaq_co2": {
"name": "CO2 air quality index"
},
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/fumis/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from .coordinator import FumisConfigEntry, FumisDataUpdateCoordinator

PLATFORMS = [Platform.CLIMATE, Platform.SENSOR]
PLATFORMS = [Platform.BUTTON, Platform.CLIMATE, Platform.SENSOR]


async def async_setup_entry(hass: HomeAssistant, entry: FumisConfigEntry) -> bool:
Expand Down
71 changes: 71 additions & 0 deletions homeassistant/components/fumis/button.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
"""Support for Fumis button entities."""

from __future__ import annotations

from collections.abc import Awaitable, Callable
from dataclasses import dataclass
from typing import Any

from fumis import Fumis

from homeassistant.components.button import ButtonEntity, ButtonEntityDescription
from homeassistant.const import EntityCategory
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback

from .coordinator import FumisConfigEntry, FumisDataUpdateCoordinator
from .entity import FumisEntity
from .helpers import fumis_exception_handler

PARALLEL_UPDATES = 1


@dataclass(frozen=True, kw_only=True)
class FumisButtonEntityDescription(ButtonEntityDescription):
"""Describes a Fumis button entity."""

press_fn: Callable[[Fumis], Awaitable[Any]]


BUTTONS: tuple[FumisButtonEntityDescription, ...] = (
FumisButtonEntityDescription(
key="sync_clock",
translation_key="sync_clock",
entity_category=EntityCategory.DIAGNOSTIC,
press_fn=lambda client: client.set_clock(),
),
)


async def async_setup_entry(
hass: HomeAssistant,
entry: FumisConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up Fumis button entities based on a config entry."""
coordinator = entry.runtime_data
async_add_entities(
FumisButtonEntity(coordinator=coordinator, description=description)
for description in BUTTONS
)


class FumisButtonEntity(FumisEntity, ButtonEntity):
"""Defines a Fumis button entity."""

entity_description: FumisButtonEntityDescription

def __init__(
self,
coordinator: FumisDataUpdateCoordinator,
description: FumisButtonEntityDescription,
) -> None:
"""Initialize the Fumis button entity."""
super().__init__(coordinator)
self.entity_description = description
self._attr_unique_id = f"{coordinator.config_entry.unique_id}_{description.key}"

@fumis_exception_handler
async def async_press(self) -> None:
"""Handle the button press."""
await self.entity_description.press_fn(self.coordinator.client)
5 changes: 5 additions & 0 deletions homeassistant/components/fumis/icons.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
{
"entity": {
"button": {
"sync_clock": {
"default": "mdi:clock-sync"
}
},
"sensor": {
"combustion_chamber_temperature": {
"default": "mdi:thermometer-high"
Expand Down
5 changes: 5 additions & 0 deletions homeassistant/components/fumis/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@
}
},
"entity": {
"button": {
"sync_clock": {
"name": "Sync clock"
}
},
"sensor": {
"combustion_chamber_temperature": {
"name": "Combustion chamber"
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/mobile_app/webhook.py
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ async def webhook_render_template(
{
vol.Optional(ATTR_LOCATION_NAME): cv.string,
vol.Optional(ATTR_GPS): cv.gps,
vol.Optional(ATTR_GPS_ACCURACY): cv.positive_int,
vol.Optional(ATTR_GPS_ACCURACY): cv.positive_float,
vol.Optional(ATTR_BATTERY): cv.positive_int,
vol.Optional(ATTR_SPEED): cv.positive_int,
vol.Optional(ATTR_ALTITUDE): vol.Coerce(float),
Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/mqtt/abbreviations.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@
"tit": "title",
"t": "topic",
"trns": "transition",
"tz": "timezone",
"uniq_id": "unique_id",
"unit_of_meas": "unit_of_measurement",
"url_t": "url_topic",
Expand Down
21 changes: 16 additions & 5 deletions homeassistant/components/mqtt/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,7 @@
"remote_code": REMOTE_CODE,
"remote_code_text": REMOTE_CODE_TEXT,
}
EXCLUDE_FROM_CONFIG_IF_NONE = {CONF_ENTITY_CATEGORY}
EXCLUDE_FROM_CONFIG_IF_NONE = {CONF_ENTITY_CATEGORY, CONF_UNIT_OF_MEASUREMENT}
PWD_NOT_CHANGED = "__**password_not_changed**__"

DEVELOPER_DOCUMENTATION_URL = "https://developers.home-assistant.io/"
Expand Down Expand Up @@ -1133,11 +1133,13 @@ def validate_number_platform_config(config: dict[str, Any]) -> dict[str, str]:
errors[CONF_MIN] = "max_below_min"
errors[CONF_MAX] = "max_below_min"

if (unit_of_measurement := config.get(CONF_UNIT_OF_MEASUREMENT)) == "None":
unit_of_measurement = None

if (
(device_class := config.get(CONF_DEVICE_CLASS)) is not None
and device_class in NUMBER_DEVICE_CLASS_UNITS
and config.get(CONF_UNIT_OF_MEASUREMENT)
not in NUMBER_DEVICE_CLASS_UNITS[device_class]
and unit_of_measurement not in NUMBER_DEVICE_CLASS_UNITS[device_class]
):
errors[CONF_UNIT_OF_MEASUREMENT] = "invalid_uom"

Expand Down Expand Up @@ -1166,6 +1168,7 @@ def validate_sensor_platform_config(
):
errors[CONF_OPTIONS] = "options_with_enum_device_class"

unit_of_measurement: str | None = None
if (
device_class in DEVICE_CLASS_UNITS
and (unit_of_measurement := config.get(CONF_UNIT_OF_MEASUREMENT)) is None
Expand All @@ -1175,6 +1178,10 @@ def validate_sensor_platform_config(
errors[CONF_UNIT_OF_MEASUREMENT] = "uom_required_for_device_class"
return errors

if unit_of_measurement == "None":
unit_of_measurement = None
config.pop(CONF_UNIT_OF_MEASUREMENT)

if (
device_class is not None
and device_class in DEVICE_CLASS_UNITS
Expand Down Expand Up @@ -4984,7 +4991,9 @@ async def async_step_export_yaml(
self._subentry_data["device"].get("mqtt_settings", {}).copy()
)
for field in EXCLUDE_FROM_CONFIG_IF_NONE:
if field in component_config and component_config[field] is None:
if field in component_config and (
component_config[field] is None or component_config[field] == "None"
):
component_config.pop(field)
mqtt_yaml_config.append({platform: component_config})

Expand Down Expand Up @@ -5033,7 +5042,9 @@ async def async_step_export_discovery(
self._subentry_data["device"].get("mqtt_settings", {}).copy()
)
for field in EXCLUDE_FROM_CONFIG_IF_NONE:
if field in component_config and component_config[field] is None:
if field in component_config and (
component_config[field] is None or component_config[field] == "None"
):
component_config.pop(field)
discovery_payload["cmps"][component_id] = component_config

Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/mqtt/config_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
Platform.CLIMATE.value: vol.All(cv.ensure_list, [dict]),
Platform.COVER.value: vol.All(cv.ensure_list, [dict]),
Platform.DATE.value: vol.All(cv.ensure_list, [dict]),
Platform.DATETIME.value: vol.All(cv.ensure_list, [dict]),
Platform.DEVICE_TRACKER.value: vol.All(cv.ensure_list, [dict]),
Platform.EVENT.value: vol.All(cv.ensure_list, [dict]),
Platform.FAN.value: vol.All(cv.ensure_list, [dict]),
Expand Down
2 changes: 2 additions & 0 deletions homeassistant/components/mqtt/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,7 @@
Platform.CLIMATE,
Platform.COVER,
Platform.DATE,
Platform.DATETIME,
Platform.DEVICE_TRACKER,
Platform.EVENT,
Platform.FAN,
Expand Down Expand Up @@ -435,6 +436,7 @@
"climate",
"cover",
"date",
"datetime",
"device_automation",
"device_tracker",
"event",
Expand Down
Loading