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

Reparation des energy meters #324

Closed
wants to merge 15 commits into from
Closed
Show file tree
Hide file tree
Changes from 9 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
39 changes: 24 additions & 15 deletions custom_components/hilo/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,7 @@ async def async_update(self) -> None:
self.check_tarif()

def set_state(self, entity, state, new_attrs={}, keep_state=False, force=False):
params = f"entity={entity}, state={state}, new_attrs={new_attrs}, keep_state={keep_state}"
params = f"{entity=} {state=} {new_attrs=} {keep_state=}"
current = self._hass.states.get(entity)
if not current:
if not force:
Expand All @@ -471,14 +471,15 @@ def set_state(self, entity, state, new_attrs={}, keep_state=False, force=False):
attrs = {}
else:
attrs = dict(current.as_dict()["attributes"])
LOG.debug(f"Setting state {params} {current}")
attrs["last_update"] = datetime.now()
attrs["hilo_update"] = True
attrs = {**attrs, **new_attrs}
if keep_state and current:
state = current.state
if "Cost" in attrs:
attrs["Cost"] = state
self._hass.states.async_set(entity, state, attrs)
LOG.debug(f"Setting state {params} {current=} {attrs=}")
self._hass.states.async_set(entity, state, attrs, force_update=force)

@property
def high_times(self):
Expand All @@ -490,32 +491,35 @@ def high_times(self):
def check_tarif(self):
if self.generate_energy_meters:
tarif = "low"
base_sensor = f"sensor.{HILO_ENERGY_TOTAL}_low"
base_sensor = f"sensor.{HILO_ENERGY_TOTAL}"
energy_used = self._hass.states.get(base_sensor)
if not energy_used:
LOG.warning(f"check_tarif: Unable to find state for {base_sensor}")
LOG.warning(f"check_tarif(): Unable to find state for {base_sensor}")
return tarif
plan_name = self.hq_plan_name
tarif_config = CONF_TARIFF.get(plan_name)
current_cost = self._hass.states.get("sensor.hilo_rate_current")
current_state = 0 if not current_cost else current_cost.state
try:
if float(energy_used.state) >= tarif_config.get("low_threshold"):
tarif = "medium"
except ValueError:
LOG.warning(
f"Unable to restore a valid state of {base_sensor}: {energy_used.state}"
f"check_tarif(): Unable to restore a valid state of {base_sensor}: {energy_used.state}"
)

if tarif_config.get("high", 0) > 0 and self.high_times:
tarif = "high"
target_cost = self._hass.states.get(f"sensor.hilo_rate_{tarif}")
if target_cost.state != current_cost.state:
if target_cost.state != current_state:
LOG.debug(
f"check_tarif: Updating current cost, was {current_cost.state} now {target_cost.state}"
f"check_tarif: Updating current cost, was {current_state=} now {target_cost.state=}"
)
self.set_state(
"sensor.hilo_rate_current", target_cost.state, force=True
)
self.set_state("sensor.hilo_rate_current", target_cost.state)
LOG.debug(
f"check_tarif: Current plan: {plan_name} Target Tarif: {tarif} Energy used: {energy_used.state} Peak: {self.high_times}"
f"check_tarif: Current plan: {plan_name} Target Tarif: {tarif} Energy used: {energy_used.state} Peak: {self.high_times} {target_cost.state=} {current_state=}"
)
known_power = 0
smart_meter = "sensor.smartenergymeter_power"
Expand Down Expand Up @@ -560,15 +564,20 @@ def check_tarif(self):

@callback
def fix_utility_sensor(self, entity, state):
"""not sure why this doesn't get created with a proper device_class"""
"""For some reason, the utility sensors are missing their
measurement units and device classes."""
current_state = state.as_dict()
attrs = current_state.get("attributes", {})
if not attrs.get("source"):
LOG.debug(f"No source entity defined on {entity}: {current_state}")
LOG.debug(
f"fix_utility_sensor(): No source entity defined on {entity}: {current_state}"
)
return
parent_unit = self._hass.states.get(attrs.get("source"))
if not parent_unit:
LOG.warning(f"Unable to find state for parent unit: {current_state}")
LOG.warning(
f"fix_utility_sensor(): Unable to find state for parent unit: {current_state}"
)
return
new_attrs = {
ATTR_UNIT_OF_MEASUREMENT: parent_unit.as_dict()
Expand All @@ -578,7 +587,7 @@ def fix_utility_sensor(self, entity, state):
}
if not all(a in attrs.keys() for a in new_attrs.keys()):
LOG.warning(
f"Fixing utility sensor: {entity} {current_state} new_attrs: {new_attrs}"
f"fix_utility_sensor(): Fixing utility sensor: {entity=} {current_state=} new_attrs: {new_attrs=}"
)
self.set_state(entity, None, new_attrs=new_attrs, keep_state=True)

Expand All @@ -588,7 +597,7 @@ def set_tarif(self, entity, current, new):
return
if entity.startswith("select.hilo_energy") and current != new:
LOG.debug(
f"check_tarif: Changing tarif of {entity} from {current} to {new}"
f"set_tarif(): Changing tarif of {entity=} from {current=} to {new=}"
)
context = Context()
data = {ATTR_OPTION: new, "entity_id": entity}
Expand Down
68 changes: 44 additions & 24 deletions custom_components/hilo/managers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,20 @@

from homeassistant.components.energy.data import async_get_manager
from homeassistant.components.utility_meter import async_setup as utility_setup
from homeassistant.components.utility_meter.const import DOMAIN as UTILITY_DOMAIN
from homeassistant.components.utility_meter.const import (
CONF_METER,
CONF_METER_DELTA_VALUES,
CONF_METER_NET_CONSUMPTION,
CONF_METER_OFFSET,
CONF_METER_PERIODICALLY_RESETTING,
CONF_METER_TYPE,
CONF_SOURCE_SENSOR,
CONF_TARIFF,
CONF_TARIFFS,
DATA_TARIFF_SENSORS,
DATA_UTILITY,
DOMAIN as UTILITY_DOMAIN,
)
from homeassistant.components.utility_meter.sensor import (
async_setup_platform as utility_setup_platform,
)
Expand All @@ -26,7 +39,7 @@ def add_meter(self, entity, tariff_list, net_consumption=False):
self.add_meter_config(entity, tariff_list, net_consumption)

def add_meter_entity(self, entity, tariff_list):
if entity in self.hass.data.get("utility_meter_data", {}):
if entity in self.hass.data.get(DATA_UTILITY, {}):
LOG.debug(f"Entity {entity} is already in the utility meters")
return
self.new_entities += 1
Expand All @@ -35,39 +48,44 @@ def add_meter_entity(self, entity, tariff_list):
meter_name = f"{name} {tarif}"
LOG.debug(f"Creating UtilityMeter entity for {entity}: {meter_name}")
self.meter_entities[meter_name] = {
"meter": entity,
CONF_METER: entity,
"name": meter_name,
"tariff": tarif,
CONF_TARIFF: tarif,
}

def add_meter_config(self, entity, tariff_list, net_consumption):
name = f"{entity}_{self.period}"
LOG.debug(
f"Creating UtilityMeter config: {name} {tariff_list} (Net Consumption: {net_consumption})"
)
self.meter_configs[entity] = OrderedDict(
{
"source": f"sensor.{entity}",
"name": name,
"cycle": self.period,
"tariffs": tariff_list,
"net_consumption": net_consumption,
"utility_meter_sensors": [],
"offset": timedelta(0),
"delta_values": False,
"periodically_resetting": True,
}
)
self.meter_configs[entity] = {
CONF_SOURCE_SENSOR: f"sensor.{entity}",
"name": name,
CONF_METER_TYPE: self.period,
CONF_TARIFFS: tariff_list,
CONF_METER_NET_CONSUMPTION: net_consumption,
DATA_TARIFF_SENSORS: [],
CONF_METER_OFFSET: timedelta(0),
CONF_METER_DELTA_VALUES: False,
CONF_METER_PERIODICALLY_RESETTING: True,
}

async def update(self, async_add_entities):
LOG.debug(f"Setting up UtilityMeter entities {UTILITY_DOMAIN}")
if self.new_entities == 0:
LOG.debug("No new entities, not setting up again")
return
config = {}
config[UTILITY_DOMAIN] = OrderedDict(
{**self.hass.data.get("utility_meter_data", {}), **self.meter_configs}
)
# NOTE(dvd): Pas sur si c'est relevant de pousser les config originale
# current_meters = self.hass.data.get(DATA_UTILITY, {})
# for meter, conf in current_meters.items():
# conf[CONF_TARIFFS] = conf.get(CONF_TARIFFS, [])
# conf[CONF_METER_OFFSET] = conf.get(CONF_METER_OFFSET, timedelta(0))
# conf[CONF_METER_DELTA_VALUES] = conf.get(CONF_METER_DELTA_VALUES, False)
# conf[CONF_METER_TYPE] = conf.get(CONF_METER_TYPE, "daily")
# conf[CONF_METER_NET_CONSUMPTION] = conf.get(CONF_METER_NET_CONSUMPTION, True)
# conf[CONF_METER_PERIODICALLY_RESETTING] = conf.get(CONF_METER_PERIODICALLY_RESETTING, True)
config = {UTILITY_DOMAIN: OrderedDict(self.meter_configs)}
LOG.debug(f"Performing utility_setup: {config=}")
await utility_setup(self.hass, config)
await utility_setup_platform(
self.hass, config, async_add_entities, self.meter_entities
Expand All @@ -80,6 +98,7 @@ def __init__(self):

@property
def msg(self):
LOG.debug(f"Updating dashboard with {self.src=} {self.dev=}")
return {
"energy_sources": self.src,
"device_consumption": self.dev,
Expand Down Expand Up @@ -117,20 +136,21 @@ def add_flow_from(self, sensor, rate):
"entity_energy_price": f"sensor.{rate}",
"number_energy_price": None,
}
LOG.debug(f"Adding {sensor} / {rate} to grid source")
LOG.debug(f"Adding from flow: {sensor} / {rate} to grid source {flow=}")
self.src[0]["flow_from"].append(flow)

def add_device(self, sensor):
sensor = f"sensor.{sensor}"
LOG.debug(f"energy dashboard: Adding {sensor} to individual device consumption")
if any(d["stat_consumption"] == sensor for d in self.dev):
return
LOG.debug(f"Adding {sensor} to individual device consumption")
self.updated = True
self.dev.append({"stat_consumption": sensor})
LOG.debug(f"energy dashboard: Added {sensor} to individual device consumption")

def add_to_dashboard(self, entity, tariff_list):
for tarif in tariff_list:
name = f"{entity}_{self.period}"
name = f"{entity}"
if entity == HILO_ENERGY_TOTAL:
self.add_flow_from(f"{name}_{tarif}", f"hilo_rate_{tarif}")
else:
Expand Down
Loading