Skip to content

Commit

Permalink
feat: import historical measurements (#17)
Browse files Browse the repository at this point in the history
* add dependency and bump version

* add import statistics

* have historic/recorder working with sum

* fix show sum in energy statistics

* update readme and bump minor version

* update readme 2

* update readme 3
  • Loading branch information
duhow authored Mar 10, 2024
1 parent a55df67 commit 697c216
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 14 deletions.
29 changes: 17 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,33 +8,32 @@ Si te gusta el proyecto, dale a ⭐ **Star** ! 😊

## :warning: NOTA: Login con usuario desactivado (CAPTCHA)

Última actualización: `2023-03-06`
Inicio del problema: Anterior a `2023-01-23`
Última actualización: `2024-03-10`

La API requiere comprobar la petición de login via CAPTCHA.
Se puede iniciar sesión pasando un Token OAuth manualmente.
Busca la 🍪 cookie `ofexTokenJwt` y copia el valor.
El token dura 1h.

Seguimiento del problema en https://github.com/duhow/hass-aigues-barcelona/issues/5 .

## Estado: 🔧 BETA - Se buscan programadores
## Uso

Esta integración ahora mismo expone un `sensor` con el último valor disponible de la lectura de agua del día de hoy.
Esta integración expone un `sensor` con el último valor disponible de la lectura de agua del día de hoy.
La lectura que se muestra, puede estar demorada **hasta 4 días o más** (normalmente es 1-2 días).

La información se consulta **cada 4 horas** para no sobresaturar el servicio.

## Uso
## Instalación

Via [HACS](https://hacs.xyz/), agrega este repositorio personalizado (https://github.com/duhow/hass-aigues-barcelona), y podrás descargar la integración.
1. Via [HACS](https://hacs.xyz/), busca e instala este componente personalizado.

Cuando lo tengas descargado, agrega la integración.
[![Install repository](https://my.home-assistant.io/badges/hacs_repository.svg)](https://my.home-assistant.io/redirect/hacs_repository/?owner=duhow&repository=hass-aigues-barcelona&category=integration)

[![Add Integration](https://my.home-assistant.io/badges/config_flow_start.svg)](https://my.home-assistant.io/redirect/config_flow_start?domain=aigues_barcelona)
2. Cuando lo tengas descargado, agrega la integración en Home Assistant.

## To-Do

- [x] Sensor de último consumo disponible
- [x] Soportar múltiples contratos
- [ ] Publicar el consumo en [Energía](https://www.home-assistant.io/docs/energy/)
[![Add Integration](https://my.home-assistant.io/badges/config_flow_start.svg)](https://my.home-assistant.io/redirect/config_flow_start?domain=aigues_barcelona)

## Ayuda

Expand All @@ -43,3 +42,9 @@ No soy un experto en Home Assistant, hay conceptos que son nuevos para mí en cu
Se agradece cualquier Pull Request si tienes conocimiento en la materia :)

Si encuentras algún error, puedes abrir un Issue.

## To-Do

- [x] Sensor de último consumo disponible
- [x] Soportar múltiples contratos
- [x] **BETA** Publicar el consumo en [Energía](https://www.home-assistant.io/docs/energy/)
5 changes: 3 additions & 2 deletions custom_components/aigues_barcelona/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@
],
"config_flow": true,
"dependencies": [
"http"
"http",
"recorder"
],
"documentation": "https://github.com/duhow/hass-aigues-barcelona/tree/master",
"integration_type": "hub",
"iot_class": "cloud_polling",
"issue_tracker": "https://github.com/duhow/hass-aigues-barcelona/issues",
"requirements": [],
"version": "0.3.1"
"version": "0.4.0"
}
73 changes: 73 additions & 0 deletions custom_components/aigues_barcelona/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@
from datetime import datetime
from datetime import timedelta

import homeassistant.components.recorder.util as recorder_util
from homeassistant.components.recorder.const import (
DATA_INSTANCE as RECORDER_DATA_INSTANCE,
)
from homeassistant.components.recorder.statistics import async_import_statistics
from homeassistant.components.recorder.statistics import clear_statistics
from homeassistant.components.recorder.statistics import list_statistic_ids
from homeassistant.components.sensor import SensorDeviceClass
from homeassistant.components.sensor import SensorEntity
from homeassistant.components.sensor import SensorStateClass
Expand Down Expand Up @@ -31,6 +38,14 @@
_LOGGER = logging.getLogger(__name__)


def get_db_instance(hass):
"""Workaround for older HA versions."""
try:
return recorder_util.get_instance(hass)
except AttributeError:
return hass


async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entities):
"""Set up entry."""
hass.data.setdefault(DOMAIN, {})
Expand Down Expand Up @@ -149,8 +164,66 @@ async def _async_update_data(self):
self._data[CONF_VALUE] = metric["accumulatedConsumption"]
self._data[CONF_STATE] = metric["datetime"]

# await self._clear_statistics()
await self._async_import_statistics(consumptions)

return True

async def _clear_statistics(self) -> None:
all_ids = await get_db_instance(self.hass).async_add_executor_job(
list_statistic_ids, self.hass
)
to_clear = [
x["statistic_id"]
for x in all_ids
if x["statistic_id"].startswith(f"sensor.contador_{self.contract}")
]

if to_clear:
_LOGGER.warn(
f"About to delete {len(to_clear)} entries from {self.contract}"
)
# NOTE: This does not seem to work?
await get_db_instance(self.hass).async_add_executor_job(
clear_statistics, self.hass.data[RECORDER_DATA_INSTANCE], to_clear
)

async def _async_import_statistics(self, consumptions) -> None:
# force sort by datetime
consumptions = sorted(
consumptions, key=lambda x: datetime.fromisoformat(x["datetime"])
)

# TODO: Hay que cargar datos historicos para actualizar sum_total desde el primer registro.
# Conforme tengamos más datos para representar, aparecerá el fallo para depurar.

stats = list()
sum_total = 0.0
for metric in consumptions:
start_ts = datetime.fromisoformat(metric["datetime"])
start_ts = start_ts.replace(minute=0, second=0, microsecond=0) # required
# round: fixes decimal with 20 digits precision
sum_total = round(sum_total + metric["deltaConsumption"], 4)
stats.append(
{
"start": start_ts,
"state": metric["accumulatedConsumption"],
# -- required to show in historic/recorder
"sum": sum_total,
# "last_reset": start_ts,
}
)
metadata = {
"has_mean": False,
"has_sum": True,
"name": None,
"source": "recorder", # required
"statistic_id": f"sensor.contador_{self.contract}",
"unit_of_measurement": UnitOfVolume.CUBIC_METERS,
}
# _LOGGER.debug(f"Adding metric: {metadata} {stats}")
async_import_statistics(self.hass, metadata, stats)


class ContadorAgua(CoordinatorEntity, SensorEntity):
"""Representation of a sensor."""
Expand Down

0 comments on commit 697c216

Please sign in to comment.