diff --git a/CHANGELOG.md b/CHANGELOG.md index d9a1f42..67b152a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## 1.1.0 +- New sensors based on ecojoko Measurements APIs +- Some performance improvement and minor bug fixes +- Bug fix [#58](https://github.com/jmcruvellier/little_monkey/issues/58) +- Bug fix [#71](https://github.com/jmcruvellier/little_monkey/issues/71) + ## 1.0.1 - Bug fix [#67](https://github.com/jmcruvellier/little_monkey/issues/67) diff --git a/README.md b/README.md index 2765213..f7ff337 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,8 @@ +[![CodeQL](https://github.com/jmcruvellier/little_monkey/actions/workflows/github-code-scanning/codeql/badge.svg)](https://github.com/jmcruvellier/little_monkey/actions/workflows/github-code-scanning/codeql) +[![HACS](https://github.com/jmcruvellier/little_monkey/actions/workflows/hacs.yaml/badge.svg)](https://github.com/jmcruvellier/little_monkey/actions/workflows/hacs.yaml) +[![hassfest](https://github.com/jmcruvellier/little_monkey/actions/workflows/hassfest.yaml/badge.svg)](https://github.com/jmcruvellier/little_monkey/actions/workflows/hassfest.yaml) +[![Validate](https://github.com/jmcruvellier/little_monkey/actions/workflows/validate.yml/badge.svg)](https://github.com/jmcruvellier/little_monkey/actions/workflows/validate.yml) + ![](/custom_components/little_monkey/res/logo_small.png) # Little Monkey / Petit Singe @@ -5,24 +10,27 @@ Cette intégration vous permet de récupérer les informations collectées par v Elle intègre dans Home Assistant les capteurs suivants: -* Consommation Temps Réel (Puissance en W) -* Consommation Réseau (Energie en kWh) -* Si vous avez un contrat d'énergie HC/HP - - Consommation HC Réseau (Energie en kWh) - - Consommation HP Réseau (Energie en kWh) - - Si c'est un contrat Tempo: - - Consommation HC Bleu Réseau (Energie en kWh) - - Consommation HP Bleu Réseau (Energie en kWh) - - Consommation HC Blanc Réseau (Energie en kWh) - - Consommation HP Blanc Réseau (Energie en kWh) - - Consommation HC Rouge Réseau (Energie en kWh) - - Consommation HP Rouge Réseau (Energie en kWh) -* Si vous êtes producteur d'énergie grâce à des panneaux photovoltaïques et possesseur d'un capteur ecojoko ancienne génération: - - Surplus de Production (Energie en kWh) -* Température Intérieure (en °C) -* Température Extérieure (en °C) -* Humidité Intérieure (en %) -* Humidité Extérieure (en %) +| Version | Capteur | Type | Unité | Disponibilité | Commentaire | +| ------- | ------- | ---- | ----- | ------------- | ----------- | +| 1.0.0 | Consommation Temps Réel | Puissance | W | Permanent | | +| 1.0.0 | Consommation Réseau | Energie | kWh | Permanent | | +| 1.0.0 | Consommation HC Réseau | Energie | kWh | Optionnel | Si vous avez un contrat d'énergie incluant les HC/HP | +| 1.0.0 | Consommation HP Réseau | Energie | kWh | Optionnel | Si vous avez un contrat d'énergie incluant les HC/HP | +| 1.0.0 | Consommation HC Bleu Réseau | Energie | kWh | Optionnel | Si vous avez un contrat d'énergie Tempo | +| 1.0.0 | Consommation HP Bleu Réseau | Energie | kWh | Optionnel | Si vous avez un contrat d'énergie Tempo | +| 1.0.0 | Consommation HC Blanc Réseau | Energie | kWh | Optionnel | Si vous avez un contrat d'énergie Tempo | +| 1.0.0 | Consommation HP Blanc Réseau | Energie | kWh | Optionnel | Si vous avez un contrat d'énergie Tempo | +| 1.0.0 | Consommation HC Rouge Réseau | Energie | kWh | Optionnel | Si vous avez un contrat d'énergie Tempo | +| 1.0.0 | Consommation HP Rouge Réseau | Energie | kWh | Optionnel | Si vous avez un contrat d'énergie Tempo | +| 1.0.0 | Surplus de Production | Energie | kWh | Optionnel | Si vous êtes producteur d'énergie grâce à des panneaux photovoltaïques et possesseur d'un capteur ecojoko ancienne génération | +| 1.0.0 | Température Intérieure | Température | °C | Optionnel | | +| 1.0.0 | Température Extérieure | Température | °C | Optionnel | | +| 1.0.0 | Humidité Intérieure | Humidité | % | Optionnel | | +| 1.0.0 | Humidité Extérieure | Humidité | % | Optionnel | | +| 1.1.0 | Consommation Dernière Mesure | Puissance | W | Optionnel | Dernière valeur retournée dans la section Mesures de l'application ecojoko | +| 1.1.0 | Consommation Réseau Dernière Mesure | Energie | kWh | Optionnel | Dernière valeur retournée dans la section Mesures de l'application ecojoko | +| 1.1.0 | Consommation HC Réseau Dernière Mesure | Energie | kWh | Optionnel | Dernière valeur retournée dans la section Mesures de l'application ecojoko | +| 1.1.0 | Consommation HP Réseau Dernière Mesure | Energie | kWh | Optionnel | Dernière valeur retournée dans la section Mesures de l'application ecojoko | > [!IMPORTANT] > Si vous êtes un utilisateur régulier de l'application ecojoko©️, vous n'êtes pas sans savoir que le petit singe glisse souvent sur sa peau de banane. **Cette __intégration non-officielle__ dépend des APIs d'ecojoko©️ et n'est donc pas responsable en cas d'indisponibilité de vos donnés.** diff --git a/custom_components/little_monkey/__init__.py b/custom_components/little_monkey/__init__.py index 281a78e..3d8b12b 100644 --- a/custom_components/little_monkey/__init__.py +++ b/custom_components/little_monkey/__init__.py @@ -14,6 +14,7 @@ from .const import ( DOMAIN, PLATFORMS, + CONF_USE_LAST_MEASURE_FEATURE, CONF_USE_HCHP_FEATURE, CONF_USE_TEMPO_FEATURE, CONF_USE_TEMPHUM_FEATURE, @@ -21,6 +22,15 @@ ) from .coordinator import LittleMonkeyDataUpdateCoordinator +def get_boolean(array, index): + """Read the value with a default of False if the key is not found.""" + return array.get(index, False) + +def get_string(array, index): + """Read the value with a default of empty string if the key is not found.""" + return array.get(index, "") + + # https://developers.home-assistant.io/docs/config_entries_index/#setting-up-an-entry async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Set up this integration using UI.""" @@ -29,12 +39,13 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: hass=hass, entry=entry, client=LittleMonkeyApiClient( - username=entry.data[CONF_USERNAME], - password=entry.data[CONF_PASSWORD], - use_hchp=entry.data[CONF_USE_HCHP_FEATURE], - use_tempo=entry.data[CONF_USE_TEMPO_FEATURE], - use_temphum=entry.data[CONF_USE_TEMPHUM_FEATURE], - use_prod=entry.data[CONF_USE_PROD_FEATURE], + username=get_string(entry.data, CONF_USERNAME), + password=get_string(entry.data, CONF_PASSWORD), + use_last_measure=get_boolean(entry.data, CONF_USE_LAST_MEASURE_FEATURE), + use_hchp=get_boolean(entry.data, CONF_USE_HCHP_FEATURE), + use_tempo=get_boolean(entry.data, CONF_USE_TEMPO_FEATURE), + use_temphum=get_boolean(entry.data, CONF_USE_TEMPHUM_FEATURE), + use_prod=get_boolean(entry.data, CONF_USE_PROD_FEATURE), session=async_get_clientsession(hass), ), ) diff --git a/custom_components/little_monkey/api.py b/custom_components/little_monkey/api.py index 73116ea..5df194e 100644 --- a/custom_components/little_monkey/api.py +++ b/custom_components/little_monkey/api.py @@ -1,8 +1,7 @@ """API Client for little_monkey.""" from __future__ import annotations -# import traceback - +#import traceback import asyncio import datetime import socket @@ -27,13 +26,11 @@ class LittleMonkeyApiClientError(Exception): """Exception to indicate a general API error.""" - class LittleMonkeyApiClientCommunicationError( LittleMonkeyApiClientError ): """Exception to indicate a communication error.""" - class LittleMonkeyApiClientAuthenticationError( LittleMonkeyApiClientError ): @@ -59,6 +56,7 @@ def __init__( self, username: str, password: str, + use_last_measure: bool, use_hchp: bool, use_tempo: bool, use_temphum: bool, @@ -68,6 +66,7 @@ def __init__( """Initialize.""" self._username = username self._password = password + self._use_last_measure = use_last_measure self._use_hchp = use_hchp self._use_tempo = use_tempo self._use_temphum = use_temphum @@ -81,6 +80,7 @@ def __init__( self._temp_hum_id = None self._current_date = None self._local_time = None + self._local_date = None self._current_pricing_details = None self._night_pricing_details = None self._day_pricing_details = None @@ -91,6 +91,9 @@ def __init__( self._kwh_hc_night = None self._kwh_hc_ns = None self._kwh_hp_ns = None + self._last_kwh = None + self._last_kwh_hc_ns = None + self._last_kwh_hp_ns = None self._tempo_hc_blue = None self._tempo_hp_blue = None self._tempo_hc_white = None @@ -102,6 +105,7 @@ def __init__( self._outdoor_temp = None self._indoor_hum = None self._outdoor_hum = None + self._last_consumption_measure = None #67 fix self._status = APIStatus.INIT @@ -115,6 +119,11 @@ def current_date(self) -> datetime.date: """Return the native value of the sensor.""" return self._current_date + @property + def local_date(self) -> datetime.time: + """Return the native value of the sensor.""" + return self._local_date + @property def local_time(self) -> datetime.time: """Return the native value of the sensor.""" @@ -155,6 +164,21 @@ def kwh_hp_ns(self) -> int: """Return the native value of the sensor.""" return self._kwh_hp_ns + @property + def last_kwh(self) -> int: + """Return the native value of the sensor.""" + return self._last_kwh + + @property + def last_kwh_hc_ns(self) -> int: + """Return the native value of the sensor.""" + return self._last_kwh_hc_ns + + @property + def last_kwh_hp_ns(self) -> int: + """Return the native value of the sensor.""" + return self._last_kwh_hp_ns + @property def tempo_hc_blue(self) -> int: """Return the native value of the sensor.""" @@ -210,6 +234,11 @@ def outdoor_hum(self) -> int: """Return the native value of the sensor.""" return self._outdoor_hum + @property + def last_consumption_measure(self) -> int: + """Return the native value of the sensor.""" + return self._last_consumption_measure + def has_day_changed(self, datetime1, datetime2): """Compare two dates and return if day has changed.""" # Extract date components (year, month, day) @@ -224,6 +253,7 @@ async def async_get_date_time(self) -> any: # Get the current date self._current_date = datetime.date.today() paris_tz = pytz.timezone('Europe/Paris') + self._local_date = datetime.datetime.now(paris_tz).date() self._local_time = datetime.datetime.now(paris_tz).time() return @@ -235,7 +265,7 @@ async def async_get_data(self) -> None: if self._gateway_id is None: await self.async_get_gatewaydata() - previous_date = self._current_date + previous_local_date = self._local_date previous_local_time = self._local_time await self.async_get_date_time() if self._current_pricingzone is None or ( @@ -259,7 +289,7 @@ async def async_get_data(self) -> None: # Retrieving Night HC night_time = datetime.time(1, 0, 0) await self.async_get_pricing_details(is_current=False, - specific_date=self._current_date, + specific_date=self._local_date, specific_time=night_time) self._kwh_hc_night = await self.async_get_powerstat(self._night_pricing_details) if self._night_pricing_details == "HC Bleu": @@ -273,7 +303,7 @@ async def async_get_data(self) -> None: # Retrieving Day HP day_time = datetime.time(14, 0, 0) await self.async_get_pricing_details(is_current=False, - specific_date=self._current_date, + specific_date=self._local_date, specific_time=day_time) kwh_hp = await self.async_get_powerstat(self._day_pricing_details) if self._day_pricing_details == "HP Bleu": @@ -284,8 +314,8 @@ async def async_get_data(self) -> None: self._tempo_hp_red = kwh_hp else: #68 fix Tempo sensors not being reset when day changes - date1 = datetime.datetime(previous_date.year, previous_date.month, previous_date.day, previous_local_time.hour, previous_local_time.minute, previous_local_time.second) - date2 = datetime.datetime(self._current_date.year, self._current_date.month, self._current_date.day, self._local_time.hour, self._local_time.minute, self._local_time.second) + date1 = datetime.datetime(previous_local_date.year, previous_local_date.month, previous_local_date.day, previous_local_time.hour, previous_local_time.minute, previous_local_time.second) + date2 = datetime.datetime(self._local_date.year, self._local_date.month, self._local_date.day, self._local_time.hour, self._local_time.minute, self._local_time.second) if self.has_day_changed(date1, date2) is True: self._kwh_hc_night = None self._tempo_hc_blue = None @@ -294,9 +324,11 @@ async def async_get_data(self) -> None: self._tempo_hp_white = None self._tempo_hc_red = None self._tempo_hp_red = None - + await self.async_get_gatewaydata() await self.async_get_realtime_conso() + if self._use_last_measure is True: + await self.async_get_last_measure() await self.async_get_kwhstat() if self._use_temphum is True: await self.async_get_tempstat() @@ -345,10 +377,6 @@ async def async_get_pricing_details(self, specific_time=specific_time) except Exception: # pylint: disable=broad-except return - # except Exception as exception: # pylint: disable=broad-except - # raise LittleMonkeyApiClientError( - # "Something really wrong happened!" - # ) from exception async def async_get_realtime_conso(self) -> any: """Get Ecojoko realtime consumption.""" @@ -365,10 +393,22 @@ async def async_get_realtime_conso(self) -> any: return await self._realtimeconso_wrapper() except Exception: # pylint: disable=broad-except return - # except Exception as exception: # pylint: disable=broad-except - # raise LittleMonkeyApiClientError( - # "Something really wrong happened!" - # ) from exception + + async def async_get_last_measure(self) -> any: + """Get Ecojoko last measure.""" + try: + if self._cookies is None: + LOGGER.debug("Pas de cookies") + # raise exception + if self._gateway_id is None: + LOGGER.debug("Pas de gateway") + # TOTO raise exception + if self._power_meter_id is None: + LOGGER.debug("Pas de power meter") + # TOTO raise exception + return await self._last_measure_wrapper() + except Exception: # pylint: disable=broad-except + return async def async_get_kwhstat(self) -> any: """Get Ecojoko kwhstat.""" @@ -385,10 +425,6 @@ async def async_get_kwhstat(self) -> any: return await self._kwhstat_wrapper() except Exception: # pylint: disable=broad-except return - # except Exception as exception: # pylint: disable=broad-except - # raise LittleMonkeyApiClientError( - # "Something really wrong happened!" - # ) from exception async def async_get_tempstat(self) -> any: """Get Ecojoko tempstat.""" @@ -405,10 +441,6 @@ async def async_get_tempstat(self) -> any: return await self._tempstat_wrapper() except Exception: # pylint: disable=broad-except return - # except Exception as exception: # pylint: disable=broad-except - # raise LittleMonkeyApiClientError( - # "Something really wrong happened!" - # ) from exception async def async_get_humstat(self) -> any: """Get Ecojoko humstat.""" @@ -425,10 +457,6 @@ async def async_get_humstat(self) -> any: return await self._humstat_wrapper() except Exception: # pylint: disable=broad-except return - # except Exception as exception: # pylint: disable=broad-except - # raise LittleMonkeyApiClientError( - # "Something really wrong happened!" - # ) from exception async def async_get_powerstat(self, pricing_details) -> any: """Get Ecojoko powerstat.""" @@ -445,10 +473,6 @@ async def async_get_powerstat(self, pricing_details) -> any: return await self._powerstat_wrapper(pricing_details) except Exception: # pylint: disable=broad-except return - # except Exception as exception: # pylint: disable=broad-except - # raise LittleMonkeyApiClientError( - # "Something really wrong happened!" - # ) from exception async def _cookiesapi_wrapper( self, @@ -463,12 +487,14 @@ async def _cookiesapi_wrapper( data=data ) if response.status in (401, 403): + #71 bug fix + self._cookies = None raise LittleMonkeyApiClientAuthenticationError( "Invalid credentials", ) self._cookies = response.cookies - response.raise_for_status() - return await response.json() + #response.raise_for_status() + return except asyncio.TimeoutError as exception: LOGGER.error("API Cookies timeout error") @@ -496,6 +522,8 @@ async def _gatewayapi_wrapper(self) -> any: cookies=self._cookies, ) if response.status in (401, 403): + #71 bug fix + self._cookies = None raise LittleMonkeyApiClientAuthenticationError( "Invalid credentials", ) @@ -519,8 +547,8 @@ async def _gatewayapi_wrapper(self) -> any: if item["device_type"] == "POWER_METER": self._power_meter_id = item["device_id"] - response.raise_for_status() - return await response.json() + #response.raise_for_status() + return except asyncio.TimeoutError as exception: LOGGER.error("API Gateway timeout error") @@ -548,7 +576,7 @@ async def _pricing_details_wrapper(self, # Retrieve current Tempo pricing # Format the date as 'YYYY-MM-DD' if specific_date is None: - formatted_date = self._current_date.strftime('%Y-%m-%d') + formatted_date = self._local_date.strftime('%Y-%m-%d') else: #67 fix formatted_date = specific_date.strftime('%Y-%m-%d') @@ -560,7 +588,6 @@ async def _pricing_details_wrapper(self, local_time = specific_time formatted_date = formatted_date + specific_time.strftime('%H:%M') url = ECOJOKO_GATEWAY_URL + f"/{self._gateway_id}/device/{self._power_meter_id}/powerstat/h/{formatted_date}" - #LOGGER.debug("URL: %s", url) async with async_timeout.timeout(CONF_API_TIMEOUT): response = await self._session.get( url=url, @@ -568,6 +595,8 @@ async def _pricing_details_wrapper(self, cookies=self._cookies, ) if response.status in (401, 403): + #71 bug fix + self._cookies = None raise LittleMonkeyApiClientAuthenticationError( "Invalid credentials", ) @@ -592,11 +621,11 @@ async def _pricing_details_wrapper(self, self._evening_pricing_details = pricing_details else: LOGGER.debug("PAS DE PRICING DETAILS") - response.raise_for_status() - return await response.json() + #response.raise_for_status() + return except asyncio.TimeoutError as exception: - LOGGER.error("API Pricing Details timeout error: %s") + LOGGER.error("API Pricing Details timeout error") raise LittleMonkeyApiClientCommunicationError( "Timeout error fetching information", ) from exception @@ -623,14 +652,16 @@ async def _realtimeconso_wrapper(self) -> any: cookies=self._cookies, ) if response.status in (401, 403): + #71 bug fix + self._cookies = None raise LittleMonkeyApiClientAuthenticationError( "Invalid credentials", ) if "application/json" in response.headers.get("Content-Type", ""): value_json = await response.json() self._realtime_conso = value_json['real_time']['value'] - response.raise_for_status() - return await response.json() + #response.raise_for_status() + return except asyncio.TimeoutError as exception: LOGGER.error("API Realtime timeout error") @@ -648,6 +679,106 @@ async def _realtimeconso_wrapper(self) -> any: "Something really wrong happened!" ) from exception + async def _last_measure_wrapper(self) -> any: + """Get last measure from the API.""" + try: + # Format the date as 'YYYY-MM-DD' + formatted_date = self._local_date.strftime('%Y-%m-%d') + url = ECOJOKO_GATEWAY_URL + f"/{self._gateway_id}/device/{self._power_meter_id}/powerstat/d4/{formatted_date}" + # formatted_date = formatted_date + self._local_time.strftime('%H:%M') + # url = ECOJOKO_GATEWAY_URL + f"/{self._gateway_id}/device/{self._power_meter_id}/powerstat/h/{formatted_date}" + async with async_timeout.timeout(CONF_API_TIMEOUT): + response = await self._session.get( + url=url, + headers=self._headers, + cookies=self._cookies, + ) + if response.status in (401, 403): + #71 bug fix + self._cookies = None + raise LittleMonkeyApiClientAuthenticationError( + "Invalid credentials", + ) + if "application/json" in response.headers.get("Content-Type", ""): + value_json = await response.json() + if "data" in value_json['stat']: + if len(value_json['stat']['data']) > 1: + self._last_consumption_measure = value_json['stat']['data'][-1]['value'] + else: + # LOGGER.debug("UNE SEULE VALEUR: %s", value_json) + self._last_consumption_measure = value_json['stat']['data']['value'] + + if "period" in value_json['stat']: + self._last_kwh = value_json['stat']['period']['kwh'] + # LOGGER.warning("REPONSE ECOJOKO: %s", value_json) + if self._use_hchp is True: + self._last_kwh_hp_ns = value_json['stat']['period']['kwh_hp_ns'] + self._last_kwh_hc_ns = value_json['stat']['period']['kwh_hc_ns'] + else: + LOGGER.debug("NE RETOURNE PAS DE HC/HP") + + #response.raise_for_status() + return #await response.json() + + except asyncio.TimeoutError as exception: + LOGGER.error("API Last Measure timeout error") + raise LittleMonkeyApiClientCommunicationError( + "Timeout error fetching information", + ) from exception + except (aiohttp.ClientError, socket.gaierror) as exception: + LOGGER.error("API Last Measure client error: %s", exception) + raise LittleMonkeyApiClientCommunicationError( + "Error fetching information", + ) from exception + except Exception as exception: # pylint: disable=broad-except + LOGGER.error("API Last Measure other error: %s", exception) + #traceback.print_exc() + raise LittleMonkeyApiClientError( + "Something really wrong happened!" + ) from exception + + async def Tempo(self) -> any: + """Tempo data analysis.""" + if self._current_pricing_details == "HC Bleu": + if self.current_pricingzone == PricingZone.HC_EVENING: + if self._kwh_hc_night is not None and self._current_pricing_details != self._night_pricing_details: + if (self._kwh_hc_ns - self._kwh_hc_night) >= 0: + self._tempo_hc_blue = self._kwh_hc_ns - self._kwh_hc_night + elif self._current_pricing_details == self._night_pricing_details: + if self._kwh_hc_ns >= 0: + self._tempo_hc_blue = self._kwh_hc_ns + else: + self._tempo_hc_blue = self._kwh_hc_ns + self._kwh_hc_night = self._kwh_hc_ns + elif self._current_pricing_details == "HP Bleu": + self._tempo_hp_blue = self._kwh_hp_ns + elif self._current_pricing_details == "HC Blanc": + if self.current_pricingzone == PricingZone.HC_EVENING: + if self._kwh_hc_night is not None and self._current_pricing_details != self._night_pricing_details: + if (self._kwh_hc_ns - self._kwh_hc_night) >= 0: + self._tempo_hc_white = self._kwh_hc_ns - self._kwh_hc_night + elif self._current_pricing_details == self._night_pricing_details: + if self._kwh_hc_ns >= 0: + self._tempo_hc_white = self._kwh_hc_ns + else: + self._tempo_hc_white = self._kwh_hc_ns + self._kwh_hc_night = self._kwh_hc_ns + elif self._current_pricing_details == "HP Blanc": + self._tempo_hp_white = self._kwh_hp_ns + elif self._current_pricing_details == "HC Rouge": + if self.current_pricingzone == PricingZone.HC_EVENING: + if self._kwh_hc_night is not None and self._current_pricing_details != self._night_pricing_details: + if (self._kwh_hc_ns - self._kwh_hc_night) >= 0: + self._tempo_hc_red = self._kwh_hc_ns - self._kwh_hc_night + elif self._current_pricing_details == self._night_pricing_details: + if self._kwh_hc_ns >= 0: + self._tempo_hc_red = self._kwh_hc_ns + else: + self._tempo_hc_red = self._kwh_hc_ns + self._kwh_hc_night = self._kwh_hc_ns + elif self._current_pricing_details == "HP Rouge": + self._tempo_hp_red = self._kwh_hp_ns + async def _kwhstat_wrapper(self) -> any: """Get kwhstat from the API.""" try: @@ -659,67 +790,70 @@ async def _kwhstat_wrapper(self) -> any: cookies=self._cookies, ) if response.status in (401, 403): + #71 bug fix + self._cookies = None raise LittleMonkeyApiClientAuthenticationError( "Invalid credentials", ) if "application/json" in response.headers.get("Content-Type", ""): value_json = await response.json() - self._kwh = value_json['stat']['period']['kwh'] - # LOGGER.warning("REPONSE ECOJOKO: %s", value_json) - if self._use_hchp is True: - self._kwh_hp_ns = value_json['stat']['period']['kwh_hp_ns'] - self._kwh_hc_ns = value_json['stat']['period']['kwh_hc_ns'] - else: - LOGGER.debug("NE RETOURNE PAS DE HC/HP") - if self._use_tempo is True: - self._kwh_hp_ns = value_json['stat']['period']['kwh_hp_ns'] - self._kwh_hc_ns = value_json['stat']['period']['kwh_hc_ns'] - #63 - if self._current_pricing_details == "HC Bleu": - if self.current_pricingzone == PricingZone.HC_EVENING: - if self._kwh_hc_night is not None and self._current_pricing_details != self._night_pricing_details: - self._tempo_hc_blue = self._kwh_hc_ns - self._kwh_hc_night - elif self._current_pricing_details == self._night_pricing_details: - self._tempo_hc_blue = self._kwh_hc_ns - # else: - # self._tempo_hc_blue = self._kwh_hc_ns - else: - self._tempo_hc_blue = self._kwh_hc_ns - self._kwh_hc_night = self._kwh_hc_ns - elif self._current_pricing_details == "HP Bleu": - self._tempo_hp_blue = self._kwh_hp_ns - elif self._current_pricing_details == "HC Blanc": - if self.current_pricingzone == PricingZone.HC_EVENING: - if self._kwh_hc_night is not None and self._current_pricing_details != self._night_pricing_details: - self._tempo_hc_white = self._kwh_hc_ns - self._kwh_hc_night - elif self._current_pricing_details == self._night_pricing_details: - self._tempo_hc_white = self._kwh_hc_ns - # else: - # self._tempo_hc_white = self._kwh_hc_ns - else: - self._tempo_hc_white = self._kwh_hc_ns - self._kwh_hc_night = self._kwh_hc_ns - elif self._current_pricing_details == "HP Blanc": - self._tempo_hp_white = self._kwh_hp_ns - elif self._current_pricing_details == "HC Rouge": - if self.current_pricingzone == PricingZone.HC_EVENING: - if self._kwh_hc_night is not None and self._current_pricing_details != self._night_pricing_details: - self._tempo_hc_red = self._kwh_hc_ns - self._kwh_hc_night - elif self._current_pricing_details == self._night_pricing_details: - self._tempo_hc_red = self._kwh_hc_ns - # else: - # self._tempo_hc_red = self._kwh_hc_ns - else: - self._tempo_hc_red = self._kwh_hc_ns - self._kwh_hc_night = self._kwh_hc_ns - elif self._current_pricing_details == "HP Rouge": - self._tempo_hp_red = self._kwh_hp_ns - if self._use_prod is True: - self._kwh_prod = -float(value_json['stat']['period']['kwh_prod']) - else: - LOGGER.debug("NE RETOURNE PAS DE PROD") - response.raise_for_status() - return await response.json() + if "period" in value_json['stat']: + self._kwh = value_json['stat']['period']['kwh'] + if self._use_hchp is True: + self._kwh_hp_ns = value_json['stat']['period']['kwh_hp_ns'] + self._kwh_hc_ns = value_json['stat']['period']['kwh_hc_ns'] + # else: + # LOGGER.debug("NE RETOURNE PAS DE HC/HP") + if self._use_tempo is True: + self._kwh_hp_ns = value_json['stat']['period']['kwh_hp_ns'] + self._kwh_hc_ns = value_json['stat']['period']['kwh_hc_ns'] + #63 + await self.Tempo() + # if self._current_pricing_details == "HC Bleu": + # if self.current_pricingzone == PricingZone.HC_EVENING: + # if self._kwh_hc_night is not None and self._current_pricing_details != self._night_pricing_details: + # if (self._kwh_hc_ns - self._kwh_hc_night) >= 0: + # self._tempo_hc_blue = self._kwh_hc_ns - self._kwh_hc_night + # elif self._current_pricing_details == self._night_pricing_details: + # if self._kwh_hc_ns >= 0: + # self._tempo_hc_blue = self._kwh_hc_ns + # else: + # self._tempo_hc_blue = self._kwh_hc_ns + # self._kwh_hc_night = self._kwh_hc_ns + # elif self._current_pricing_details == "HP Bleu": + # self._tempo_hp_blue = self._kwh_hp_ns + # elif self._current_pricing_details == "HC Blanc": + # if self.current_pricingzone == PricingZone.HC_EVENING: + # if self._kwh_hc_night is not None and self._current_pricing_details != self._night_pricing_details: + # if (self._kwh_hc_ns - self._kwh_hc_night) >= 0: + # self._tempo_hc_white = self._kwh_hc_ns - self._kwh_hc_night + # elif self._current_pricing_details == self._night_pricing_details: + # if self._kwh_hc_ns >= 0: + # self._tempo_hc_white = self._kwh_hc_ns + # else: + # self._tempo_hc_white = self._kwh_hc_ns + # self._kwh_hc_night = self._kwh_hc_ns + # elif self._current_pricing_details == "HP Blanc": + # self._tempo_hp_white = self._kwh_hp_ns + # elif self._current_pricing_details == "HC Rouge": + # if self.current_pricingzone == PricingZone.HC_EVENING: + # if self._kwh_hc_night is not None and self._current_pricing_details != self._night_pricing_details: + # if (self._kwh_hc_ns - self._kwh_hc_night) >= 0: + # self._tempo_hc_red = self._kwh_hc_ns - self._kwh_hc_night + # elif self._current_pricing_details == self._night_pricing_details: + # if self._kwh_hc_ns >= 0: + # self._tempo_hc_red = self._kwh_hc_ns + # else: + # self._tempo_hc_red = self._kwh_hc_ns + # self._kwh_hc_night = self._kwh_hc_ns + # elif self._current_pricing_details == "HP Rouge": + # self._tempo_hp_red = self._kwh_hp_ns + if self._use_prod is True: + self._kwh_prod = -float(value_json['stat']['period']['kwh_prod']) + # else: + # LOGGER.debug("NE RETOURNE PAS DE PROD") + #response.raise_for_status() + return except asyncio.TimeoutError as exception: LOGGER.error("API KWHSTAT timeout error") @@ -741,11 +875,8 @@ async def _kwhstat_wrapper(self) -> any: async def _tempstat_wrapper(self) -> any: """Get tempstat from the API.""" try: - #59 bug fix - # Get the current date - current_date = datetime.date.today() # Format the date as 'YYYY-MM-DD' - formatted_date = current_date.strftime('%Y-%m-%d') + formatted_date = self._local_date.strftime('%Y-%m-%d') url = ECOJOKO_GATEWAY_URL + f"/{self._gateway_id}/device/{self._temp_hum_id}/tempstat/d4/{formatted_date}" async with async_timeout.timeout(CONF_API_TIMEOUT): response = await self._session.get( @@ -754,20 +885,23 @@ async def _tempstat_wrapper(self) -> any: cookies=self._cookies, ) if response.status in (401, 403): + #71 bug fix + self._cookies = None raise LittleMonkeyApiClientAuthenticationError( "Invalid credentials", ) if "application/json" in response.headers.get("Content-Type", ""): value_json = await response.json() - if len(value_json['stat']['data']) > 1: - self._indoor_temp = value_json['stat']['data'][-1]['value'] - self._outdoor_temp = value_json['stat']['data'][-1]['ext_value'] - else: - # LOGGER.debug("TEMP UNE SEULE VALEUR: %s", value_json) - self._indoor_temp = value_json['stat']['data']['value'] - self._outdoor_temp = value_json['stat']['data']['ext_value'] - response.raise_for_status() - return await response.json() + if "data" in value_json['stat']: + if len(value_json['stat']['data']) > 1: + self._indoor_temp = value_json['stat']['data'][-1]['value'] + self._outdoor_temp = value_json['stat']['data'][-1]['ext_value'] + else: + # LOGGER.debug("TEMP UNE SEULE VALEUR: %s", value_json) + self._indoor_temp = value_json['stat']['data']['value'] + self._outdoor_temp = value_json['stat']['data']['ext_value'] + #response.raise_for_status() + return except asyncio.TimeoutError as exception: LOGGER.error("API TEMPSTAT timeout error") @@ -788,11 +922,8 @@ async def _tempstat_wrapper(self) -> any: async def _humstat_wrapper(self) -> any: """Get humstat from the API.""" try: - #59 bug fix - # Get the current date - current_date = datetime.date.today() # Format the date as 'YYYY-MM-DD' - formatted_date = current_date.strftime('%Y-%m-%d') + formatted_date = self._local_date.strftime('%Y-%m-%d') url = ECOJOKO_GATEWAY_URL + f"/{self._gateway_id}/device/{self._temp_hum_id}/humstat/d4/{formatted_date}" async with async_timeout.timeout(CONF_API_TIMEOUT): response = await self._session.get( @@ -801,20 +932,23 @@ async def _humstat_wrapper(self) -> any: cookies=self._cookies, ) if response.status in (401, 403): + #71 bug fix + self._cookies = None raise LittleMonkeyApiClientAuthenticationError( "Invalid credentials", ) if "application/json" in response.headers.get("Content-Type", ""): value_json = await response.json() - if len(value_json['stat']['data']) > 1: - self._indoor_hum = value_json['stat']['data'][-1]['value'] - self._outdoor_hum = value_json['stat']['data'][-1]['ext_value'] - else: - # LOGGER.debug("HUM UNE SEULE VALEUR: %s", value_json) - self._indoor_hum = value_json['stat']['data']['value'] - self._outdoor_hum = value_json['stat']['data']['ext_value'] - response.raise_for_status() - return await response.json() + if "data" in value_json['stat']: + if len(value_json['stat']['data']) > 1: + self._indoor_hum = value_json['stat']['data'][-1]['value'] + self._outdoor_hum = value_json['stat']['data'][-1]['ext_value'] + else: + # LOGGER.debug("HUM UNE SEULE VALEUR: %s", value_json) + self._indoor_hum = value_json['stat']['data']['value'] + self._outdoor_hum = value_json['stat']['data']['ext_value'] + #response.raise_for_status() + return except asyncio.TimeoutError as exception: LOGGER.error("API HUMSTAT timeout error") @@ -836,10 +970,8 @@ async def _powerstat_wrapper(self, pricing_details) -> any: """Get powerstat from the API.""" try: result = None - # Get the current date - current_date = datetime.date.today() # Format the date as 'YYYY-MM-DD' - formatted_date = current_date.strftime('%Y-%m-%d') + formatted_date = self._local_date.strftime('%Y-%m-%d') url = ECOJOKO_GATEWAY_URL + f"/{self._gateway_id}/device/{self._power_meter_id}/powerstat/w/{formatted_date}" async with async_timeout.timeout(CONF_API_TIMEOUT): response = await self._session.get( @@ -848,18 +980,22 @@ async def _powerstat_wrapper(self, pricing_details) -> any: cookies=self._cookies, ) if response.status in (401, 403): + #71 bug fix + self._cookies = None raise LittleMonkeyApiClientAuthenticationError( "Invalid credentials", ) + result = None if "application/json" in response.headers.get("Content-Type", ""): value_json = await response.json() - week_day = self._current_date.weekday() - if len(value_json['stat']['data']) > week_day: - for subconscomption in value_json['stat']['data'][week_day]['subconsumption']: - if subconscomption['label'] == pricing_details: - result = subconscomption['kwh'] - break - return result + if "data" in value_json['stat']: + week_day = self._local_date.weekday() + if len(value_json['stat']['data']) > week_day: + for subconscomption in value_json['stat']['data'][week_day]['subconsumption']: + if subconscomption['label'] == pricing_details: + result = subconscomption['kwh'] + break + return result except asyncio.TimeoutError as exception: LOGGER.error("API HUMSTAT timeout error") diff --git a/custom_components/little_monkey/config_flow.py b/custom_components/little_monkey/config_flow.py index fbe1304..38cacd9 100644 --- a/custom_components/little_monkey/config_flow.py +++ b/custom_components/little_monkey/config_flow.py @@ -22,6 +22,7 @@ DOMAIN, POLL_INTERVAL, DEFAULT_POLL_INTERVAL, + CONF_USE_LAST_MEASURE_FEATURE, CONF_USE_HCHP_FEATURE, CONF_USE_TEMPO_FEATURE, CONF_USE_TEMPHUM_FEATURE, @@ -48,6 +49,9 @@ def _get_data_schema(config_entry: config_entries.ConfigEntry | None = None) -> type=selector.TextSelectorType.PASSWORD ), ), + vol.Optional( + CONF_USE_LAST_MEASURE_FEATURE, default=False, + ): cv.boolean, vol.Optional( CONF_USE_HCHP_FEATURE, default=False, ): cv.boolean, @@ -97,6 +101,9 @@ def _get_data_schema(config_entry: config_entries.ConfigEntry | None = None) -> type=selector.TextSelectorType.PASSWORD ), ), + vol.Optional( + CONF_USE_LAST_MEASURE_FEATURE, default=config_entry.data.get(CONF_USE_LAST_MEASURE_FEATURE), + ): cv.boolean, vol.Optional( CONF_USE_HCHP_FEATURE, default=config_entry.data.get(CONF_USE_HCHP_FEATURE), ): cv.boolean, @@ -151,6 +158,7 @@ async def async_step_user( await self._get_cookies( username=user_input[CONF_USERNAME], password=user_input[CONF_PASSWORD], + use_last_measure=user_input[CONF_USE_LAST_MEASURE_FEATURE], use_hchp=user_input[CONF_USE_HCHP_FEATURE], use_tempo=user_input[CONF_USE_TEMPO_FEATURE], use_temphum=user_input[CONF_USE_TEMPHUM_FEATURE], @@ -178,10 +186,11 @@ async def async_step_user( errors=_errors, ) - async def _get_cookies(self, username: str, password: str, use_hchp: bool, use_temphum: bool, use_tempo: bool, use_prod: bool) -> None: + async def _get_cookies(self, username: str, password: str, use_last_measure: bool, use_hchp: bool, use_temphum: bool, use_tempo: bool, use_prod: bool) -> None: client = LittleMonkeyApiClient( username=username, password=password, + use_last_measure=use_last_measure, use_hchp=use_hchp, use_tempo=use_tempo, use_temphum=use_temphum, @@ -223,6 +232,7 @@ async def async_step_init( client = await self._get_cookies( username=user_input[CONF_USERNAME], password=user_input[CONF_PASSWORD], + use_last_measure=user_input[CONF_USE_LAST_MEASURE_FEATURE], use_hchp=user_input[CONF_USE_HCHP_FEATURE], use_tempo=user_input[CONF_USE_TEMPO_FEATURE], use_temphum=user_input[CONF_USE_TEMPHUM_FEATURE], @@ -246,10 +256,11 @@ async def async_step_init( errors=self._errors, ) - async def _get_cookies(self, username: str, password: str, use_hchp: bool, use_tempo: bool, use_temphum: bool, use_prod: bool) -> LittleMonkeyApiClient: + async def _get_cookies(self, username: str, password: str, use_last_measure: bool, use_hchp: bool, use_tempo: bool, use_temphum: bool, use_prod: bool) -> LittleMonkeyApiClient: client = LittleMonkeyApiClient( username=username, password=password, + use_last_measure=use_last_measure, use_hchp=use_hchp, use_tempo=use_tempo, use_temphum=use_temphum, diff --git a/custom_components/little_monkey/const.py b/custom_components/little_monkey/const.py index 50a689a..9f89845 100644 --- a/custom_components/little_monkey/const.py +++ b/custom_components/little_monkey/const.py @@ -7,7 +7,7 @@ DOMAIN = "little_monkey" MANUFACTURER = "Jean-Marc Cruvellier" MODEL = "Ecojoko" -VERSION = "1.0.1" +VERSION = "1.1.0" ATTRIBUTION = "Data provided by https://service.ecojoko.com//" POLL_INTERVAL = "poll_interval" DEFAULT_POLL_INTERVAL = "5" @@ -17,6 +17,7 @@ CONF_USE_TEMPO_FEATURE = "use_tempo_feature" CONF_USE_TEMPHUM_FEATURE = "use_temphum_feature" CONF_USE_PROD_FEATURE = "use_prod_feature" +CONF_USE_LAST_MEASURE_FEATURE = "use_last_measure_feature" CONF_LANG = 'lang' DEFAULT_LANG = 'fr-FR' # Language Supported Codes diff --git a/custom_components/little_monkey/coordinator.py b/custom_components/little_monkey/coordinator.py index 2d5e7e4..f49ac4d 100644 --- a/custom_components/little_monkey/coordinator.py +++ b/custom_components/little_monkey/coordinator.py @@ -79,6 +79,10 @@ async def _async_update_data(self): "grid_consumption": self.client.kwh, "hc_grid_consumption": self.client.kwh_hc_ns, "hp_grid_consumption": self.client.kwh_hp_ns, + "last_consumption_measure": self.client.last_consumption_measure, + "last_grid_consumption_measure": self.client.last_kwh, + "last_hc_grid_consumption_measure": self.client.last_kwh_hc_ns, + "last_hp_grid_consumption_measure": self.client.last_kwh_hp_ns, "blue_hc_grid_consumption": self.client.tempo_hc_blue, "blue_hp_grid_consumption": self.client.tempo_hp_blue, "white_hc_grid_consumption": self.client.tempo_hc_white, diff --git a/custom_components/little_monkey/little_monkey_translations/en.json b/custom_components/little_monkey/little_monkey_translations/en.json index 6f1ee2f..32f9f1a 100644 --- a/custom_components/little_monkey/little_monkey_translations/en.json +++ b/custom_components/little_monkey/little_monkey_translations/en.json @@ -13,5 +13,9 @@ "indoor_temp": "Indoor Temperature", "outdoor_temp": "Outdoor Temperature", "indoor_hum": "Indoor Humidity", - "outdoor_hum": "Outdoor Humidity" + "outdoor_hum": "Outdoor Humidity", + "last_consumption_measure": "Last Consumption Measure", + "last_grid_consumption_measure": "Last Grid Consumption Measure", + "last_hc_grid_consumption_measure": "Last HC Grid Consumption Measure", + "last_hp_grid_consumption_measure": "Last HP Grid Consumption Measure" } \ No newline at end of file diff --git a/custom_components/little_monkey/little_monkey_translations/fr.json b/custom_components/little_monkey/little_monkey_translations/fr.json index e7274b3..d62b693 100644 --- a/custom_components/little_monkey/little_monkey_translations/fr.json +++ b/custom_components/little_monkey/little_monkey_translations/fr.json @@ -13,5 +13,9 @@ "indoor_temp": "Température Intérieure", "outdoor_temp": "Température Extérieure", "indoor_hum": "Humidité Intérieure", - "outdoor_hum": "Humidité Extérieure" + "outdoor_hum": "Humidité Extérieure", + "last_consumption_measure": "Consommation Dernière Mesure", + "last_grid_consumption_measure": "Consommation Réseau Dernière Mesure", + "last_hc_grid_consumption_measure": "Consommation HC Réseau Dernière Mesure", + "last_hp_grid_consumption_measure": "Consommation HP Réseau Dernière Mesure" } \ No newline at end of file diff --git a/custom_components/little_monkey/manifest.json b/custom_components/little_monkey/manifest.json index 72f6a3d..7b0b6ec 100644 --- a/custom_components/little_monkey/manifest.json +++ b/custom_components/little_monkey/manifest.json @@ -5,9 +5,9 @@ "@jmcruvellier" ], "config_flow": true, - "documentation": "https://github.com/jmcruvellier/little_monkey/blob/v0.1.1/README.md", + "documentation": "https://github.com/jmcruvellier/little_monkey/blob/v1.1.0/README.md", "integration_type": "device", "iot_class": "cloud_polling", "issue_tracker": "https://github.com/jmcruvellier/little_monkey/issues", - "version": "1.0.1" + "version": "1.1.0" } \ No newline at end of file diff --git a/custom_components/little_monkey/sensor.py b/custom_components/little_monkey/sensor.py index c62b5cb..230d067 100644 --- a/custom_components/little_monkey/sensor.py +++ b/custom_components/little_monkey/sensor.py @@ -13,7 +13,8 @@ CONF_USE_HCHP_FEATURE, CONF_USE_TEMPO_FEATURE, CONF_USE_TEMPHUM_FEATURE, - CONF_USE_PROD_FEATURE + CONF_USE_PROD_FEATURE, + CONF_USE_LAST_MEASURE_FEATURE ) async def async_setup_entry(hass, config_entry, async_add_entities): @@ -148,4 +149,30 @@ async def async_setup_entry(hass, config_entry, async_add_entities): PERCENTAGE, "mdi:water")) + # Last Consumption Measure sensor + if config_entry.data.get(CONF_USE_LAST_MEASURE_FEATURE) is True: + main_device.add_child_entity(EcojokoSensor( + main_device, + "last_consumption_measure", + SensorStateClass.MEASUREMENT, + SensorDeviceClass.POWER, + UnitOfPower.WATT, + "mdi:flash")) + # Last HC/HP grid consumption measure sensors + if config_entry.data.get(CONF_USE_HCHP_FEATURE) is True: + main_device.add_child_entity(EcojokoSensor( + main_device, + "last_hc_grid_consumption_measure", + SensorStateClass.TOTAL_INCREASING, + SensorDeviceClass.ENERGY, + UnitOfEnergy.KILO_WATT_HOUR, + "mdi:lightning-bolt")) + main_device.add_child_entity(EcojokoSensor( + main_device, + "last_hp_grid_consumption_measure", + SensorStateClass.TOTAL_INCREASING, + SensorDeviceClass.ENERGY, + UnitOfEnergy.KILO_WATT_HOUR, + "mdi:lightning-bolt")) + async_add_entities([main_device] + main_device.child_entities) diff --git a/custom_components/little_monkey/translations/en.json b/custom_components/little_monkey/translations/en.json index 5b2df8b..ddfab7a 100644 --- a/custom_components/little_monkey/translations/en.json +++ b/custom_components/little_monkey/translations/en.json @@ -8,6 +8,7 @@ "name": "Name", "username": "Username", "password": "Password", + "use_last_measure_feature": "Last measure sensors", "use_hchp_feature": "HP/HC sensors", "use_tempo_feature": "Tempo Blue/White/Red sensors", "use_temphum_feature": "Humidity and temperature sensors", @@ -30,6 +31,7 @@ "name": "Name", "username": "Username", "password": "Password", + "use_last_measure_feature": "Last measure sensors", "use_hchp_feature": "HP/HC sensors", "use_tempo_feature": "Tempo Blue/White/Red sensors", "use_temphum_feature": "Humidity and temperature sensors", diff --git a/custom_components/little_monkey/translations/fr.json b/custom_components/little_monkey/translations/fr.json index 7b79f08..3d0b9b4 100644 --- a/custom_components/little_monkey/translations/fr.json +++ b/custom_components/little_monkey/translations/fr.json @@ -8,6 +8,7 @@ "name": "Nom", "username": "Nom d'utilisateur", "password": "Mot de passe", + "use_last_measure_feature": "Capteurs de dernières mesures", "use_hchp_feature": "Capteurs HP/HC", "use_tempo_feature": "Capteurs Tempo Bleu/Blanc/Rouge", "use_temphum_feature": "Capteurs d'humidité et de température", @@ -30,6 +31,7 @@ "name": "Nom", "username": "Nom d'utilisateur", "password": "Mot de passe", + "use_last_measure_feature": "Capteurs de dernières mesures", "use_hchp_feature": "Capteurs HP/HC", "use_tempo_feature": "Capteurs Tempo Bleu/Blanc/Rouge", "use_temphum_feature": "Capteurs d'humidité et de température", diff --git a/info.md b/info.md index 353918c..4df1f27 100644 --- a/info.md +++ b/info.md @@ -1,3 +1,8 @@ +[![CodeQL](https://github.com/jmcruvellier/little_monkey/actions/workflows/github-code-scanning/codeql/badge.svg)](https://github.com/jmcruvellier/little_monkey/actions/workflows/github-code-scanning/codeql) +[![HACS](https://github.com/jmcruvellier/little_monkey/actions/workflows/hacs.yaml/badge.svg)](https://github.com/jmcruvellier/little_monkey/actions/workflows/hacs.yaml) +[![hassfest](https://github.com/jmcruvellier/little_monkey/actions/workflows/hassfest.yaml/badge.svg)](https://github.com/jmcruvellier/little_monkey/actions/workflows/hassfest.yaml) +[![Validate](https://github.com/jmcruvellier/little_monkey/actions/workflows/validate.yml/badge.svg)](https://github.com/jmcruvellier/little_monkey/actions/workflows/validate.yml) + ![](/custom_components/little_monkey/res/logo_small.png) # Little Monkey / Petit Singe @@ -5,24 +10,27 @@ Cette intégration vous permet de récupérer les informations collectées par v Elle intègre dans Home Assistant les capteurs suivants: -* Consommation Temps Réel (Puissance en W) -* Consommation Réseau (Energie en kWh) -* Si vous avez un contrat d'énergie HC/HP - - Consommation HC Réseau (Energie en kWh) - - Consommation HP Réseau (Energie en kWh) - - Si c'est un contrat Tempo: - - Consommation HC Bleu Réseau (Energie en kWh) - - Consommation HP Bleu Réseau (Energie en kWh) - - Consommation HC Blanc Réseau (Energie en kWh) - - Consommation HP Blanc Réseau (Energie en kWh) - - Consommation HC Rouge Réseau (Energie en kWh) - - Consommation HP Rouge Réseau (Energie en kWh) -* Si vous êtes producteur d'énergie grâce à des panneaux photovoltaïques et possesseur d'un capteur ecojoko ancienne génération: - - Surplus de Production (Energie en kWh) -* Température Intérieure (en °C) -* Température Extérieure (en °C) -* Humidité Intérieure (en %) -* Humidité Extérieure (en %) +| Version | Capteur | Type | Unité | Disponibilité | Commentaire | +| ------- | ------- | ---- | ----- | ------------- | ----------- | +| 1.0.0 | Consommation Temps Réel | Puissance | W | Permanent | | +| 1.0.0 | Consommation Réseau | Energie | kWh | Permanent | | +| 1.0.0 | Consommation HC Réseau | Energie | kWh | Optionnel | Si vous avez un contrat d'énergie incluant les HC/HP | +| 1.0.0 | Consommation HP Réseau | Energie | kWh | Optionnel | Si vous avez un contrat d'énergie incluant les HC/HP | +| 1.0.0 | Consommation HC Bleu Réseau | Energie | kWh | Optionnel | Si vous avez un contrat d'énergie Tempo | +| 1.0.0 | Consommation HP Bleu Réseau | Energie | kWh | Optionnel | Si vous avez un contrat d'énergie Tempo | +| 1.0.0 | Consommation HC Blanc Réseau | Energie | kWh | Optionnel | Si vous avez un contrat d'énergie Tempo | +| 1.0.0 | Consommation HP Blanc Réseau | Energie | kWh | Optionnel | Si vous avez un contrat d'énergie Tempo | +| 1.0.0 | Consommation HC Rouge Réseau | Energie | kWh | Optionnel | Si vous avez un contrat d'énergie Tempo | +| 1.0.0 | Consommation HP Rouge Réseau | Energie | kWh | Optionnel | Si vous avez un contrat d'énergie Tempo | +| 1.0.0 | Surplus de Production | Energie | kWh | Optionnel | Si vous êtes producteur d'énergie grâce à des panneaux photovoltaïques et possesseur d'un capteur ecojoko ancienne génération | +| 1.0.0 | Température Intérieure | Température | °C | Optionnel | | +| 1.0.0 | Température Extérieure | Température | °C | Optionnel | | +| 1.0.0 | Humidité Intérieure | Humidité | % | Optionnel | | +| 1.0.0 | Humidité Extérieure | Humidité | % | Optionnel | | +| 1.1.0 | Consommation Dernière Mesure | Puissance | W | Optionnel | Dernière valeur retournée dans la section Mesures de l'application ecojoko | +| 1.1.0 | Consommation Réseau Dernière Mesure | Energie | kWh | Optionnel | Dernière valeur retournée dans la section Mesures de l'application ecojoko | +| 1.1.0 | Consommation HC Réseau Dernière Mesure | Energie | kWh | Optionnel | Dernière valeur retournée dans la section Mesures de l'application ecojoko | +| 1.1.0 | Consommation HP Réseau Dernière Mesure | Energie | kWh | Optionnel | Dernière valeur retournée dans la section Mesures de l'application ecojoko | > [!IMPORTANT] > Si vous êtes un utilisateur régulier de l'application ecojoko©️, vous n'êtes pas sans savoir que le petit singe glisse souvent sur sa peau de banane. **Cette __intégration non-officielle__ dépend des APIs d'ecojoko©️ et n'est donc pas responsable en cas d'indisponibilité de vos donnés.**