Skip to content

Commit

Permalink
Merge 22cc190 into ab4b579
Browse files Browse the repository at this point in the history
  • Loading branch information
bramstroker committed Jul 8, 2023
2 parents ab4b579 + 22cc190 commit caac230
Show file tree
Hide file tree
Showing 9 changed files with 101 additions and 17 deletions.
3 changes: 3 additions & 0 deletions custom_components/powercalc/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

from .common import SourceEntity, create_source_entity
from .const import (
CONF_AREA,
CONF_CALCULATION_ENABLED_CONDITION,
CONF_CALIBRATE,
CONF_CREATE_ENERGY_SENSOR,
Expand Down Expand Up @@ -873,6 +874,7 @@ def _create_group_options_schema(hass: HomeAssistant) -> vol.Schema:
),
),
vol.Optional(CONF_SUB_GROUPS): _create_group_selector(hass, multiple=True),
vol.Optional(CONF_AREA): selector.AreaSelector(),
vol.Optional(
CONF_CREATE_UTILITY_METERS,
default=False,
Expand Down Expand Up @@ -915,6 +917,7 @@ def _validate_group_input(user_input: dict[str, Any] | None = None) -> dict:
and CONF_GROUP_POWER_ENTITIES not in user_input
and CONF_GROUP_ENERGY_ENTITIES not in user_input
and CONF_GROUP_MEMBER_SENSORS not in user_input
and CONF_AREA not in user_input
):
errors["base"] = "group_mandatory"

Expand Down
18 changes: 17 additions & 1 deletion custom_components/powercalc/group_include/include.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
CONF_FILTER,
CONF_GROUP,
CONF_TEMPLATE,
DATA_CONFIGURED_ENTITIES,
DOMAIN,
)
from custom_components.powercalc.errors import SensorConfigurationError

Expand All @@ -23,8 +25,22 @@
_LOGGER = logging.getLogger(__name__)


def resolve_include_entities(hass: HomeAssistant, include_config: dict) -> list:
powercalc_entities = []
source_entities = resolve_include_source_entities(hass, include_config)
_LOGGER.debug("Found include entities: %s", source_entities)
for source_entity in source_entities:
if source_entity.entity_id in hass.data[DOMAIN][DATA_CONFIGURED_ENTITIES]:
powercalc_entities.extend(
hass.data[DOMAIN][DATA_CONFIGURED_ENTITIES][
source_entity.entity_id
],
)
return powercalc_entities


@callback
def resolve_include_entities(
def resolve_include_source_entities(
hass: HomeAssistant,
include_config: dict,
) -> list[entity_registry.RegistryEntry]:
Expand Down
12 changes: 2 additions & 10 deletions custom_components/powercalc/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -557,7 +557,7 @@ def convert_config_entry_to_sensor_config(config_entry: ConfigEntry) -> ConfigTy
return sensor_config


async def create_sensors( # noqa: C901
async def create_sensors(
hass: HomeAssistant,
config: ConfigType,
discovery_info: DiscoveryInfoType | None = None,
Expand Down Expand Up @@ -616,15 +616,7 @@ async def create_sensors( # noqa: C901

# Automatically add a bunch of entities by area or evaluating template
if CONF_INCLUDE in config:
include_entities = resolve_include_entities(hass, config.get(CONF_INCLUDE)) # type: ignore
_LOGGER.debug("Found include entities: %s", include_entities)
for source_entity in include_entities:
if source_entity.entity_id in hass.data[DOMAIN][DATA_CONFIGURED_ENTITIES]:
entities_to_add.existing.extend(
hass.data[DOMAIN][DATA_CONFIGURED_ENTITIES][
source_entity.entity_id
],
)
entities_to_add.existing.extend(resolve_include_entities(hass, config.get(CONF_INCLUDE))) # type: ignore

# Create sensors for each entity
for sensor_config in sensor_configs.values():
Expand Down
13 changes: 11 additions & 2 deletions custom_components/powercalc/sensors/group.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
from custom_components.powercalc.const import (
ATTR_ENTITIES,
ATTR_IS_GROUP,
CONF_AREA,
CONF_DISABLE_EXTENDED_ATTRIBUTES,
CONF_ENERGY_SENSOR_PRECISION,
CONF_ENERGY_SENSOR_UNIT_PREFIX,
Expand All @@ -71,6 +72,7 @@
SensorType,
UnitPrefix,
)
from custom_components.powercalc.group_include.include import resolve_include_entities

from .abstract import (
BaseEntity,
Expand Down Expand Up @@ -168,8 +170,13 @@ async def create_group_sensors_from_config_entry(
if CONF_UNIQUE_ID not in sensor_config:
sensor_config[CONF_UNIQUE_ID] = entry.entry_id

area_entities: list[Entity] = []
if CONF_AREA in entry.data:
area_entities = resolve_include_entities(hass, {CONF_AREA: entry.data[CONF_AREA]})

power_sensor_ids: set[str] = set(
resolve_entity_ids_recursively(hass, entry, SensorDeviceClass.POWER),
resolve_entity_ids_recursively(hass, entry, SensorDeviceClass.POWER) +
[entity.entity_id for entity in area_entities if isinstance(entity, PowerSensor)],
)
if power_sensor_ids:
power_sensor = create_grouped_power_sensor(
Expand All @@ -181,7 +188,8 @@ async def create_group_sensors_from_config_entry(
group_sensors.append(power_sensor)

energy_sensor_ids: set[str] = set(
resolve_entity_ids_recursively(hass, entry, SensorDeviceClass.ENERGY),
resolve_entity_ids_recursively(hass, entry, SensorDeviceClass.ENERGY) +
[entity.entity_id for entity in area_entities if isinstance(entity, EnergySensor)],
)
if energy_sensor_ids:
energy_sensor = create_grouped_energy_sensor(
Expand Down Expand Up @@ -350,6 +358,7 @@ def resolve_entity_ids_recursively(
_LOGGER.error(f"Subgroup config entry not found: {subgroup_entry_id}")
continue
resolve_entity_ids_recursively(hass, subgroup_entry, device_class, resolved_ids)

return resolved_ids


Expand Down
2 changes: 1 addition & 1 deletion custom_components/powercalc/strategy/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ async def _create_composite(
power_profile: PowerProfile | None,
source_entity: SourceEntity,
) -> CompositeStrategy:
sub_strategies = config.get(CONF_COMPOSITE) # type: ignore
sub_strategies = list(config.get(CONF_COMPOSITE)) # type: ignore

async def _create_sub_strategy(strategy_config: ConfigType) -> SubStrategy:
condition_instance = None
Expand Down
6 changes: 5 additions & 1 deletion custom_components/powercalc/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,16 @@
"group_power_entities": "Additional power entities",
"group_energy_entities": "Additional energy entities",
"sub_groups": "Sub groups",
"area": "Area",
"hide_members": "Hide members",
"create_utility_meters": "[%key:component::powercalc::config::step::virtual_power::data::create_utility_meters%]"
},
"data_description": {
"group_member_sensors": "Powercalc sensors to include in the group",
"group_power_entities": "Additional power sensors (W) from your HA installation to include",
"group_energy_entities": "Additional energy sensors (kWh) from your HA installation to include",
"sub_groups": "All containing sensors from the selected subgroups will be added to this group as well"
"sub_groups": "All containing sensors from the selected subgroups will be added to this group as well",
"area": "Adds all powercalc sensors from the specified area"
}
},
"virtual_power": {
Expand Down Expand Up @@ -191,6 +193,7 @@
"group_member_sensors": "[%key:component::powercalc::config::step::group::data::group_member_sensors%]",
"group_power_entities": "[%key:component::powercalc::config::step::group::data::group_power_entities%]",
"group_energy_entities": "[%key:component::powercalc::config::step::group::data::group_energy_entities%]",
"area": "[%key:component::powercalc::config::step::group::data::area%]",
"sub_groups": "[%key:component::powercalc::config::step::group::data::sub_groups%]",
"hide_members": "[%key:component::powercalc::config::step::group::data::hide_members%]",
"energy_integration_method": "[%key:component::powercalc::config::step::power_advanced::data::energy_integration_method%]",
Expand All @@ -204,6 +207,7 @@
"attribute": "[%key:component::powercalc::config::step::linear::data_description::attribute%]",
"power_template": "[%key:component::powercalc::config::step::fixed::data_description::power_template%]",
"states_power": "[%key:component::powercalc::config::step::fixed::data_description::states_power%]",
"area": "[%key:component::powercalc::config::step::group::data_description::area%]",
"sub_groups": "[%key:component::powercalc::config::step::group::data_description::sub_groups%]",
"group_member_sensors": "[%key:component::powercalc::config::step::group::data_description::group_member_sensors%]",
"group_power_entities": "[%key:component::powercalc::config::step::group::data_description::group_power_entities%]",
Expand Down
6 changes: 5 additions & 1 deletion custom_components/powercalc/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,16 @@
"group_energy_entities": "Additional energy entities",
"name": "Name",
"sub_groups": "Sub groups",
"area": "Area",
"hide_members": "Hide members",
"unique_id": "Unique id"
},
"data_description": {
"group_member_sensors": "Powercalc sensors to include in the group",
"group_power_entities": "Additional power sensors (W) from your HA installation to include",
"group_energy_entities": "Additional energy sensors (kWh) from your HA installation to include",
"sub_groups": "All containing sensors from the selected subgroups will be added to this group as well"
"sub_groups": "All containing sensors from the selected subgroups will be added to this group as well",
"area": "Adds all powercalc sensors from the specified area"
},
"title": "Create a group sensor"
},
Expand Down Expand Up @@ -179,6 +181,7 @@
"step": {
"init": {
"data": {
"area": "Area",
"attribute": "Attribute",
"calculation_enabled_condition": "Calculation enabled condition",
"calibrate": "Calibration values",
Expand Down Expand Up @@ -208,6 +211,7 @@
"value_template": "Value template"
},
"data_description": {
"area": "Adds all powercalc sensors from the specified area",
"attribute": "Specify the attribute. When left empty will be brightness for lights and percentage for fans",
"calculation_enabled_condition": "The configured power calculation strategy will only be executed when this template evaluates to true or 1, otherwise the power sensor will display 0",
"calibrate": "Put a calibration value on each line. Example\n\n1: 20",
Expand Down
6 changes: 5 additions & 1 deletion custom_components/powercalc/translations/nl.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,16 @@
"group_power_entities": "Additionele vermogen entiteiten",
"name": "Naam",
"sub_groups": "Sub groepen",
"area": "Ruimte",
"hide_members": "Verberg onderliggende sensoren",
"unique_id": "Uniek id"
},
"data_description": {
"group_member_sensors": "Powercalc sensoren die je wil toevoegen aan de groep",
"group_power_entities": "Additionele vermogen entiteiten (W)",
"group_energy_entities": "Additionele energie entiteiten (kWh)",
"sub_groups": "Alle onderliggende sensoren van de geselecteerde sub-groepen worden ook automatisch aan deze groep toegevoegd."
"sub_groups": "Alle onderliggende sensoren van de geselecteerde sub-groepen worden ook automatisch aan deze groep toegevoegd.",
"area": "Voeg alle powercalc sensoren van de gespecificeerde ruimte toe"
},
"title": "Creëer een groep sensor"
},
Expand Down Expand Up @@ -179,6 +181,7 @@
"step": {
"init": {
"data": {
"area": "Ruimte",
"attribute": "Attribuut",
"calculation_enabled_condition": "Calculatie ingeschakeld conditie",
"calibrate": "Kalibratie waardes",
Expand Down Expand Up @@ -208,6 +211,7 @@
"value_template": "Waarde template"
},
"data_description": {
"area": "Voeg alle powercalc sensoren van de gespecificeerde ruimte toe",
"attribute": "Specificeer een attribuut. Wanneer je dit leeg laat dan wordt helderheid gebruikt voor verlichting en percentage voor ventilatoren",
"calculation_enabled_condition": "De geconfigureerde vermogen calculatie strategie wordt alleen uitgevoerd indien dit template evalueert naar 1, anders zal de energiesensor 0 tonen",
"calibrate": "Kalibratiewaarde op iedere regel. Voorbeeld\n\n1: 20",
Expand Down
52 changes: 52 additions & 0 deletions tests/test_config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from homeassistant import config_entries, data_entry_flow
from homeassistant.components import sensor
from homeassistant.const import (
CONF_ENTITIES,
CONF_ENTITY_ID,
CONF_NAME,
CONF_PLATFORM,
Expand All @@ -17,6 +18,8 @@
)
from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResult
from homeassistant.helpers.area_registry import AreaRegistry
from homeassistant.helpers.entity_registry import EntityRegistry
from homeassistant.helpers.selector import SelectSelector
from homeassistant.helpers.typing import ConfigType
from homeassistant.setup import async_setup_component
Expand All @@ -29,6 +32,7 @@
MENU_OPTION_LIBRARY,
)
from custom_components.powercalc.const import (
CONF_AREA,
CONF_CALCULATION_ENABLED_CONDITION,
CONF_CREATE_ENERGY_SENSOR,
CONF_CREATE_UTILITY_METERS,
Expand Down Expand Up @@ -708,6 +712,54 @@ async def test_create_group_entry_without_unique_id(hass: HomeAssistant) -> None
assert hass.states.get("sensor.my_group_sensor_power")


async def test_group_include_area(hass: HomeAssistant, entity_reg: EntityRegistry,
area_reg: AreaRegistry) -> None:

# Create light entity and add to group My area
light = MockLight("test")
await create_mock_light_entity(hass, light)
area = area_reg.async_get_or_create("My area")
entity_reg.async_update_entity(light.entity_id, area_id=area.id)

result = await _goto_virtual_power_strategy_step(hass, CalculationStrategy.FIXED, {CONF_ENTITY_ID: "light.test"})
await _set_virtual_power_configuration(
hass,
result,
{CONF_STATES_POWER: {"playing": 1.8}},
)

result = await _select_sensor_type(hass, SensorType.GROUP)
user_input = {
CONF_NAME: "My group sensor",
CONF_AREA: area.id,
CONF_CREATE_UTILITY_METERS: True,
}
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input,
)
assert result["type"] == data_entry_flow.FlowResultType.CREATE_ENTRY
assert result["data"] == {
CONF_SENSOR_TYPE: SensorType.GROUP,
CONF_NAME: "My group sensor",
CONF_HIDE_MEMBERS: False,
CONF_AREA: area.id,
CONF_UNIQUE_ID: "My group sensor",
CONF_CREATE_UTILITY_METERS: True,
}
await hass.async_block_till_done()

power_state = hass.states.get("sensor.my_group_sensor_power")
assert power_state
assert power_state.attributes.get(CONF_ENTITIES) == {"sensor.test_power"}

energy_state = hass.states.get("sensor.my_group_sensor_energy")
assert energy_state
assert energy_state.attributes.get(CONF_ENTITIES) == {"sensor.test_energy"}

assert hass.states.get("sensor.my_group_sensor_energy_daily")


async def test_can_select_existing_powercalc_entry_as_group_member(
hass: HomeAssistant,
) -> None:
Expand Down

0 comments on commit caac230

Please sign in to comment.