Skip to content

Commit

Permalink
Merge branch 'dev' into point-oauth
Browse files Browse the repository at this point in the history
  • Loading branch information
joostlek authored Sep 19, 2024
2 parents f407cc9 + 5864591 commit 7480149
Show file tree
Hide file tree
Showing 99 changed files with 890 additions and 502 deletions.
2 changes: 1 addition & 1 deletion homeassistant/components/buienradar/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -888,7 +888,7 @@ def _load_data(self, data): # noqa: C901
if sensor_type.startswith(PRECIPITATION_FORECAST):
result = {ATTR_ATTRIBUTION: data.get(ATTRIBUTION)}
if self._timeframe is not None:
result[TIMEFRAME_LABEL] = "%d min" % (self._timeframe)
result[TIMEFRAME_LABEL] = f"{self._timeframe} min"

self._attr_extra_state_attributes = result

Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/buienradar/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ async def get_data(self, url):
if resp.status == HTTPStatus.OK:
result[SUCCESS] = True
else:
result[MESSAGE] = "Got http statuscode: %d" % (resp.status)
result[MESSAGE] = f"Got http statuscode: {resp.status}"

return result
except (TimeoutError, aiohttp.ClientError) as err:
Expand Down
6 changes: 2 additions & 4 deletions homeassistant/components/emoncms_history/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,15 +86,13 @@ def update_emoncms(time):
continue

if payload_dict:
payload = "{{{}}}".format(
",".join(f"{key}:{val}" for key, val in payload_dict.items())
)
payload = ",".join(f"{key}:{val}" for key, val in payload_dict.items())

send_data(
conf.get(CONF_URL),
conf.get(CONF_API_KEY),
str(conf.get(CONF_INPUTNODE)),
payload,
f"{{{payload}}}",
)

track_point_in_time(
Expand Down
12 changes: 7 additions & 5 deletions homeassistant/components/fritzbox/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,14 +135,16 @@ def target_temperature(self) -> float:

async def async_set_temperature(self, **kwargs: Any) -> None:
"""Set new target temperature."""
if kwargs.get(ATTR_HVAC_MODE) is not None:
hvac_mode = kwargs[ATTR_HVAC_MODE]
target_temp = kwargs.get(ATTR_TEMPERATURE)
hvac_mode = kwargs.get(ATTR_HVAC_MODE)
if hvac_mode == HVACMode.OFF:
await self.async_set_hvac_mode(hvac_mode)
elif kwargs.get(ATTR_TEMPERATURE) is not None:
temperature = kwargs[ATTR_TEMPERATURE]
elif target_temp is not None:
await self.hass.async_add_executor_job(
self.data.set_target_temperature, temperature
self.data.set_target_temperature, target_temp
)
else:
return
await self.coordinator.async_refresh()

@property
Expand Down
3 changes: 1 addition & 2 deletions homeassistant/components/graphite/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,7 @@ def _report_attributes(self, entity_id, new_state):
with suppress(ValueError):
things["state"] = state.state_as_number(new_state)
lines = [
"%s.%s.%s %f %i"
% (self._prefix, entity_id, key.replace(" ", "_"), value, now)
f"{self._prefix}.{entity_id}.{key.replace(' ', '_')} {value:f} {now}"
for key, value in things.items()
if isinstance(value, (float, int))
]
Expand Down
9 changes: 1 addition & 8 deletions homeassistant/components/habitica/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,7 @@ async def _async_update_data(self) -> HabiticaData:
try:
user_response = await self.api.user.get()
tasks_response = await self.api.tasks.user.get()
tasks_response.extend(
[
{"id": task["_id"], **task}
for task in await self.api.tasks.user.get(type="completedTodos")
if task.get("_id")
]
)

tasks_response.extend(await self.api.tasks.user.get(type="completedTodos"))
except ClientResponseError as error:
if error.status == HTTPStatus.TOO_MANY_REQUESTS:
_LOGGER.debug("Currently rate limited, skipping update")
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/home_connect/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ def get_program_sensors(self):
ATTR_DEVICE: self,
ATTR_DESC: k,
ATTR_UNIT: unit,
ATTR_KEY: "BSH.Common.Option.{}".format(k.replace(" ", "")),
ATTR_KEY: f"BSH.Common.Option.{k.replace(' ', '')}",
ATTR_ICON: icon,
ATTR_DEVICE_CLASS: device_class,
ATTR_SIGN: sign,
Expand Down
38 changes: 36 additions & 2 deletions homeassistant/components/humidifier/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
SERVICE_TURN_ON,
STATE_ON,
)
from homeassistant.core import HomeAssistant
from homeassistant.core import HomeAssistant, ServiceCall
from homeassistant.exceptions import ServiceValidationError
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.deprecation import (
all_with_deprecated_constants,
Expand All @@ -45,7 +46,13 @@
DOMAIN,
MODE_AUTO,
MODE_AWAY,
MODE_BABY,
MODE_BOOST,
MODE_COMFORT,
MODE_ECO,
MODE_HOME,
MODE_NORMAL,
MODE_SLEEP,
SERVICE_SET_HUMIDITY,
SERVICE_SET_MODE,
HumidifierAction,
Expand Down Expand Up @@ -108,7 +115,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
vol.Coerce(int), vol.Range(min=0, max=100)
)
},
"async_set_humidity",
async_service_humidity_set,
)

return True
Expand Down Expand Up @@ -281,6 +288,33 @@ def supported_features_compat(self) -> HumidifierEntityFeature:
return features


async def async_service_humidity_set(
entity: HumidifierEntity, service_call: ServiceCall
) -> None:
"""Handle set humidity service."""
humidity = service_call.data[ATTR_HUMIDITY]
min_humidity = entity.min_humidity
max_humidity = entity.max_humidity
_LOGGER.debug(
"Check valid humidity %d in range %d - %d",
humidity,
min_humidity,
max_humidity,
)
if humidity < min_humidity or humidity > max_humidity:
raise ServiceValidationError(
translation_domain=DOMAIN,
translation_key="humidity_out_of_range",
translation_placeholders={
"humidity": str(humidity),
"min_humidity": str(min_humidity),
"max_humidity": str(max_humidity),
},
)

await entity.async_set_humidity(humidity)


# As we import deprecated constants from the const module, we need to add these two functions
# otherwise this module will be logged for using deprecated constants and not the custom component
# These can be removed if no deprecated constant are in this module anymore
Expand Down
5 changes: 5 additions & 0 deletions homeassistant/components/humidifier/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -115,5 +115,10 @@
"name": "[%key:common::action::toggle%]",
"description": "Toggles the humidifier on/off."
}
},
"exceptions": {
"humidity_out_of_range": {
"message": "Provided humidity {humidity} is not valid. Accepted range is {min_humidity} to {max_humidity}."
}
}
}
4 changes: 4 additions & 0 deletions homeassistant/components/iskra/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,9 @@
ATTR_PHASE2_CURRENT = "phase2_current"
ATTR_PHASE3_CURRENT = "phase3_current"

# Counters
ATTR_NON_RESETTABLE_COUNTER = "non_resettable_counter_{}"
ATTR_RESETTABLE_COUNTER = "resettable_counter_{}"

# Frequency
ATTR_FREQUENCY = "frequency"
57 changes: 56 additions & 1 deletion homeassistant/components/iskra/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
from __future__ import annotations

from collections.abc import Callable
from dataclasses import dataclass
from dataclasses import dataclass, replace

from pyiskra.devices import Device
from pyiskra.helper import Counter, CounterType

from homeassistant.components.sensor import (
SensorDeviceClass,
Expand All @@ -17,6 +18,7 @@
UnitOfApparentPower,
UnitOfElectricCurrent,
UnitOfElectricPotential,
UnitOfEnergy,
UnitOfFrequency,
UnitOfPower,
UnitOfReactivePower,
Expand All @@ -27,6 +29,7 @@
from . import IskraConfigEntry
from .const import (
ATTR_FREQUENCY,
ATTR_NON_RESETTABLE_COUNTER,
ATTR_PHASE1_CURRENT,
ATTR_PHASE1_POWER,
ATTR_PHASE1_VOLTAGE,
Expand All @@ -36,6 +39,7 @@
ATTR_PHASE3_CURRENT,
ATTR_PHASE3_POWER,
ATTR_PHASE3_VOLTAGE,
ATTR_RESETTABLE_COUNTER,
ATTR_TOTAL_ACTIVE_POWER,
ATTR_TOTAL_APPARENT_POWER,
ATTR_TOTAL_REACTIVE_POWER,
Expand Down Expand Up @@ -163,6 +167,44 @@ class IskraSensorEntityDescription(SensorEntityDescription):
)


def get_counter_entity_description(
counter: Counter,
index: int,
entity_name: str,
) -> IskraSensorEntityDescription:
"""Dynamically create IskraSensor object as energy meter's counters are customizable."""

key = entity_name.format(index + 1)

if entity_name == ATTR_NON_RESETTABLE_COUNTER:
entity_description = IskraSensorEntityDescription(
key=key,
translation_key=key,
state_class=SensorStateClass.TOTAL_INCREASING,
value_func=lambda device: device.counters.non_resettable[index].value,
native_unit_of_measurement=counter.units,
)
else:
entity_description = IskraSensorEntityDescription(
key=key,
translation_key=key,
state_class=SensorStateClass.TOTAL_INCREASING,
value_func=lambda device: device.counters.resettable[index].value,
native_unit_of_measurement=counter.units,
)

# Set unit of measurement and device class based on counter type
# HA's Energy device class supports only active energy
if counter.counter_type in [CounterType.ACTIVE_IMPORT, CounterType.ACTIVE_EXPORT]:
entity_description = replace(
entity_description,
native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
device_class=SensorDeviceClass.ENERGY,
)

return entity_description


async def async_setup_entry(
hass: HomeAssistant,
entry: IskraConfigEntry,
Expand Down Expand Up @@ -205,6 +247,19 @@ async def async_setup_entry(
if description.key in sensors
)

if device.supports_counters:
for index, counter in enumerate(device.counters.non_resettable[:4]):
description = get_counter_entity_description(
counter, index, ATTR_NON_RESETTABLE_COUNTER
)
entities.append(IskraSensor(coordinator, description))

for index, counter in enumerate(device.counters.resettable[:8]):
description = get_counter_entity_description(
counter, index, ATTR_RESETTABLE_COUNTER
)
entities.append(IskraSensor(coordinator, description))

async_add_entities(entities)


Expand Down
36 changes: 36 additions & 0 deletions homeassistant/components/iskra/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,42 @@
},
"phase3_current": {
"name": "Phase 3 current"
},
"non_resettable_counter_1": {
"name": "Non Resettable counter 1"
},
"non_resettable_counter_2": {
"name": "Non Resettable counter 2"
},
"non_resettable_counter_3": {
"name": "Non Resettable counter 3"
},
"non_resettable_counter_4": {
"name": "Non Resettable counter 4"
},
"resettable_counter_1": {
"name": "Resettable counter 1"
},
"resettable_counter_2": {
"name": "Resettable counter 2"
},
"resettable_counter_3": {
"name": "Resettable counter 3"
},
"resettable_counter_4": {
"name": "Resettable counter 4"
},
"resettable_counter_5": {
"name": "Resettable counter 5"
},
"resettable_counter_6": {
"name": "Resettable counter 6"
},
"resettable_counter_7": {
"name": "Resettable counter 7"
},
"resettable_counter_8": {
"name": "Resettable counter 8"
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/kira/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ def load_module(platform, idx, module_conf):
"""Set up the KIRA module and load platform."""
# note: module_name is not the HA device name. it's just a unique name
# to ensure the component and platform can share information
module_name = ("%s_%d" % (DOMAIN, idx)) if idx else DOMAIN
module_name = f"{DOMAIN}_{idx}" if idx else DOMAIN
device_name = module_conf.get(CONF_NAME, DOMAIN)
port = module_conf.get(CONF_PORT, DEFAULT_PORT)
host = module_conf.get(CONF_HOST, DEFAULT_HOST)
Expand Down
4 changes: 2 additions & 2 deletions homeassistant/components/limitlessled/light.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,13 +119,13 @@ def rewrite_legacy(config: ConfigType) -> ConfigType:
else:
_LOGGER.warning("Legacy configuration format detected")
for i in range(1, 5):
name_key = "group_%d_name" % i
name_key = f"group_{i}_name"
if name_key in bridge_conf:
groups.append(
{
"number": i,
"type": bridge_conf.get(
"group_%d_type" % i, DEFAULT_LED_TYPE
f"group_{i}_type", DEFAULT_LED_TYPE
),
"name": bridge_conf.get(name_key),
}
Expand Down
6 changes: 4 additions & 2 deletions homeassistant/components/mysensors/light.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,8 @@ def _turn_on_rgb(self, **kwargs: Any) -> None:
new_rgb: tuple[int, int, int] | None = kwargs.get(ATTR_RGB_COLOR)
if new_rgb is None:
return
hex_color = "{:02x}{:02x}{:02x}".format(*new_rgb)
red, green, blue = new_rgb
hex_color = f"{red:02x}{green:02x}{blue:02x}"
self.gateway.set_child_value(
self.node_id, self.child_id, self.value_type, hex_color, ack=1
)
Expand Down Expand Up @@ -220,7 +221,8 @@ def _turn_on_rgbw(self, **kwargs: Any) -> None:
new_rgbw: tuple[int, int, int, int] | None = kwargs.get(ATTR_RGBW_COLOR)
if new_rgbw is None:
return
hex_color = "{:02x}{:02x}{:02x}{:02x}".format(*new_rgbw)
red, green, blue, white = new_rgbw
hex_color = f"{red:02x}{green:02x}{blue:02x}{white:02x}"
self.gateway.set_child_value(
self.node_id, self.child_id, self.value_type, hex_color, ack=1
)
Expand Down
5 changes: 3 additions & 2 deletions homeassistant/components/netio/switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ def get(self, request, host):
states, consumptions, cumulated_consumptions, start_dates = [], [], [], []

for i in range(1, 5):
out = "output%d" % i
out = f"output{i}"
states.append(data.get(f"{out}_state") == STATE_ON)
consumptions.append(float(data.get(f"{out}_consumption", 0)))
cumulated_consumptions.append(
Expand Down Expand Up @@ -168,7 +168,8 @@ def turn_off(self, **kwargs: Any) -> None:
def _set(self, value):
val = list("uuuu")
val[int(self.outlet) - 1] = "1" if value else "0"
self.netio.get("port list {}".format("".join(val)))
val = "".join(val)
self.netio.get(f"port list {val}")
self.netio.states[int(self.outlet) - 1] = value
self.schedule_update_ha_state()

Expand Down
Loading

0 comments on commit 7480149

Please sign in to comment.