From 5e150a00aab14409466021fc259e0e89bb47c803 Mon Sep 17 00:00:00 2001 From: eifinger Date: Sun, 11 Apr 2021 21:58:36 +0200 Subject: [PATCH 1/2] update dwd --- custom_components/dwd_weather/connector.py | 510 +++++++++----------- custom_components/dwd_weather/const.py | 2 +- custom_components/dwd_weather/manifest.json | 4 +- custom_components/dwd_weather/sensor.py | 39 +- 4 files changed, 256 insertions(+), 299 deletions(-) diff --git a/custom_components/dwd_weather/connector.py b/custom_components/dwd_weather/connector.py index 08ba95e..71e4fad 100644 --- a/custom_components/dwd_weather/connector.py +++ b/custom_components/dwd_weather/connector.py @@ -1,7 +1,7 @@ """Connector class to retrieve data, which is use by the weather and sensor enities.""" import logging -import math from datetime import datetime, timedelta, timezone +import time from homeassistant.components.weather import ( ATTR_FORECAST_CONDITION, @@ -11,6 +11,7 @@ ATTR_FORECAST_TIME, ) from simple_dwd_weatherforecast import dwdforecast +from simple_dwd_weatherforecast.dwdforecast import WeatherDataType from .const import ( ATTR_ISSUE_TIME, @@ -53,160 +54,182 @@ async def async_update(self): def _update(self): """Get the latest data from DWD and generate forecast array.""" - self.dwd_weather.update() - if self.dwd_weather.get_station_name(False) == "": - _LOGGER.exception("No update possible") - else: - _LOGGER.info("Updating {}".format(self.dwd_weather.get_station_name(False))) - self.infos[ATTR_LATEST_UPDATE] = datetime.now(timezone.utc) - self.latest_update = datetime.now(timezone.utc) - self.infos[ATTR_ISSUE_TIME] = self.dwd_weather.issue_time - self.infos[ATTR_STATION_ID] = self.dwd_weather.station_id - self.infos[ATTR_STATION_NAME] = self.dwd_weather.get_station_name(False) - - _LOGGER.debug( - "forecast_data for station_id '{}': {}".format( - self.station_id, self.dwd_weather.forecast_data + timestamp = datetime.now(timezone.utc) + # Only update on the hour and when not updated yet + if timestamp.minute == 0 or self.latest_update is None: + self.dwd_weather.update() + if self.dwd_weather.get_station_name(False) == "": + _LOGGER.exception("No update possible") + else: + _LOGGER.info( + "Updating {}".format(self.dwd_weather.get_station_name(False)) ) - ) - forecast_data = [] - timestamp = datetime.now(timezone.utc) - timestep = datetime( - timestamp.year, timestamp.month, timestamp.day, tzinfo=timezone.utc - ) - # Find the next timewindow from actual time - while timestep < timestamp: - timestep += timedelta(hours=self.weather_interval) - # Reduce by one to include the current timewindow - timestep -= timedelta(hours=self.weather_interval) - for _ in range(0, 9): - for _ in range(int(24 / self.weather_interval)): - temp_max = self.dwd_weather.get_timeframe_max( - dwdforecast.WeatherDataType.TEMPERATURE, - timestep, - self.weather_interval, - False, - ) - if temp_max is not None: - temp_max = int(round(temp_max - 273.1, 0)) - - temp_min = self.dwd_weather.get_timeframe_min( - dwdforecast.WeatherDataType.TEMPERATURE, - timestep, - self.weather_interval, - False, - ) - if temp_min is not None: - temp_min = int(round(temp_min - 273.1, 0)) - - precipitation_prop = self.dwd_weather.get_timeframe_max( - dwdforecast.WeatherDataType.PRECIPITATION_PROBABILITY, - timestep, - self.weather_interval, - False, - ) - if precipitation_prop is not None: - precipitation_prop = int(precipitation_prop) - forecast_data.append( - { - ATTR_FORECAST_TIME: timestep.strftime("%Y-%m-%dT%H:00:00Z"), - ATTR_FORECAST_CONDITION: self.dwd_weather.get_timeframe_condition( - timestep, - self.weather_interval, - False, - ), - ATTR_FORECAST_TEMP: temp_max, - ATTR_FORECAST_TEMP_LOW: temp_min, - ATTR_FORECAST_PRECIPITATION: self.dwd_weather.get_timeframe_sum( - dwdforecast.WeatherDataType.PRECIPITATION, - timestep, - self.weather_interval, - False, - ), - "precipitation_probability": precipitation_prop, # ATTR_FORECAST_PRECIPITATION_PROBABILITY - } + self.infos[ATTR_LATEST_UPDATE] = timestamp + self.latest_update = timestamp + self.infos[ATTR_ISSUE_TIME] = self.dwd_weather.issue_time + self.infos[ATTR_STATION_ID] = self.dwd_weather.station_id + self.infos[ATTR_STATION_NAME] = self.dwd_weather.get_station_name(False) + + _LOGGER.debug( + "forecast_data for station_id '{}': {}".format( + self.station_id, self.dwd_weather.forecast_data ) + ) + forecast_data = [] + timestep = datetime( + timestamp.year, timestamp.month, timestamp.day, tzinfo=timezone.utc + ) + # Find the next timewindow from actual time + while timestep < timestamp: timestep += timedelta(hours=self.weather_interval) - self.forecast = forecast_data + # Reduce by one to include the current timewindow + timestep -= timedelta(hours=self.weather_interval) + for _ in range(0, 9): + for _ in range(int(24 / self.weather_interval)): + temp_max = self.dwd_weather.get_timeframe_max( + WeatherDataType.TEMPERATURE, + timestep, + self.weather_interval, + False, + ) + if temp_max is not None: + temp_max = int(round(temp_max - 273.1, 0)) + + temp_min = self.dwd_weather.get_timeframe_min( + WeatherDataType.TEMPERATURE, + timestep, + self.weather_interval, + False, + ) + if temp_min is not None: + temp_min = int(round(temp_min - 273.1, 0)) + + precipitation_prop = self.dwd_weather.get_timeframe_max( + WeatherDataType.PRECIPITATION_PROBABILITY, + timestep, + self.weather_interval, + False, + ) + if precipitation_prop is not None: + precipitation_prop = int(precipitation_prop) + forecast_data.append( + { + ATTR_FORECAST_TIME: timestep.strftime( + "%Y-%m-%dT%H:00:00Z" + ), + ATTR_FORECAST_CONDITION: self.dwd_weather.get_timeframe_condition( + timestep, + self.weather_interval, + False, + ), + ATTR_FORECAST_TEMP: temp_max, + ATTR_FORECAST_TEMP_LOW: temp_min, + ATTR_FORECAST_PRECIPITATION: self.dwd_weather.get_timeframe_sum( + WeatherDataType.PRECIPITATION, + timestep, + self.weather_interval, + False, + ), + "precipitation_probability": precipitation_prop, # ATTR_FORECAST_PRECIPITATION_PROBABILITY + } + ) + timestep += timedelta(hours=self.weather_interval) + self.forecast = forecast_data def get_condition(self): return self.dwd_weather.get_forecast_condition( datetime.now(timezone.utc), False ) - def get_temperature(self): + def get_weather_value(self, data_type: WeatherDataType): value = self.dwd_weather.get_forecast_data( - dwdforecast.WeatherDataType.TEMPERATURE, + data_type, datetime.now(timezone.utc), False, ) if value is not None: - return value - 273.1 + if data_type == WeatherDataType.TEMPERATURE: + value = round(value - 273.1, 1) + elif data_type == WeatherDataType.DEWPOINT: + value = round(value - 273.1, 1) + elif data_type == WeatherDataType.PRESSURE: + value = round(value / 100, 1) + elif data_type == WeatherDataType.WIND_SPEED: + value = round(value * 3.6, 1) + elif data_type == WeatherDataType.WIND_DIRECTION: + value = round(value, 0) + elif data_type == WeatherDataType.WIND_GUSTS: + value = round(value, 1) + elif data_type == WeatherDataType.PRECIPITATION: + value = round(value, 1) + elif data_type == WeatherDataType.PRECIPITATION_PROBABILITY: + value = round(value, 0) + elif data_type == WeatherDataType.PRECIPITATION_DURATION: + value = round(value, 1) + elif data_type == WeatherDataType.CLOUD_COVERAGE: + value = round(value, 0) + elif data_type == WeatherDataType.VISIBILITY: + value = round(value / 1000, 1) + elif data_type == WeatherDataType.SUN_DURATION: + value = round(value, 0) + elif data_type == WeatherDataType.SUN_IRRADIANCE: + value = round(value, 0) + elif data_type == WeatherDataType.FOG_PROBABILITY: + value = round(value, 0) + elif data_type == WeatherDataType.HUMIDITY: + value = round(value, 1) + + return value + + def get_temperature(self): + return self.get_weather_value(WeatherDataType.TEMPERATURE) + + def get_dewpoint(self): + return self.get_weather_value(WeatherDataType.DEWPOINT) def get_pressure(self): - value = self.dwd_weather.get_forecast_data( - dwdforecast.WeatherDataType.PRESSURE, - datetime.now(timezone.utc), - False, - ) - if value is not None: - return value / 100 + return self.get_weather_value(WeatherDataType.PRESSURE) def get_wind_speed(self): - value = self.dwd_weather.get_forecast_data( - dwdforecast.WeatherDataType.WIND_SPEED, - datetime.now(timezone.utc), - False, - ) - if value is not None: - return round( - value * 3.6, - 1, - ) + return self.get_weather_value(WeatherDataType.WIND_SPEED) def get_wind_direction(self): - return self.dwd_weather.get_forecast_data( - dwdforecast.WeatherDataType.WIND_DIRECTION, - datetime.now(timezone.utc), - False, - ) + return self.get_weather_value(WeatherDataType.WIND_DIRECTION) + + def get_wind_gusts(self): + return self.get_weather_value(WeatherDataType.WIND_GUSTS) + + def get_precipitation(self): + return self.get_weather_value(WeatherDataType.PRECIPITATION) + + def get_precipitation_probability(self): + return self.get_weather_value(WeatherDataType.PRECIPITATION_PROBABILITY) + + def get_precipitation_duration(self): + return self.get_weather_value(WeatherDataType.PRECIPITATION_DURATION) + + def get_cloud_coverage(self): + return self.get_weather_value(WeatherDataType.CLOUD_COVERAGE) def get_visibility(self): - value = self.dwd_weather.get_forecast_data( - dwdforecast.WeatherDataType.VISIBILITY, - datetime.now(timezone.utc), - False, - ) - if value is not None: - return round( - value / 1000, - 1, - ) + return self.get_weather_value(WeatherDataType.VISIBILITY) + + def get_sun_duration(self): + return self.get_weather_value(WeatherDataType.SUN_DURATION) + + def get_sun_irradiance(self): + return self.get_weather_value(WeatherDataType.SUN_IRRADIANCE) + + def get_fog_probability(self): + return self.get_weather_value(WeatherDataType.FOG_PROBABILITY) def get_humidity(self): - rh_c2 = 17.5043 - rh_c3 = 241.2 - T = self.dwd_weather.get_forecast_data( - dwdforecast.WeatherDataType.TEMPERATURE, - datetime.now(timezone.utc), - False, - ) - TD = self.dwd_weather.get_forecast_data( - dwdforecast.WeatherDataType.DEWPOINT, datetime.now(timezone.utc), False - ) - if T is not None and TD is not None: - T -= 273.1 - TD -= 273.1 - _LOGGER.debug("T: {}, TD: {}".format(T, TD)) - RH = 100 * math.exp((rh_c2 * TD / (rh_c3 + TD)) - (rh_c2 * T / (rh_c3 + T))) - return round(RH, 1) + return self.get_weather_value(WeatherDataType.HUMIDITY) def get_condition_hourly(self): data = [] for key in self.dwd_weather.forecast_data: - item = self.dwd_weather.forecast_data[key][ - dwdforecast.WeatherDataType.CONDITION.value - ] + item = self.dwd_weather.forecast_data[key][WeatherDataType.CONDITION.value] if item != "-": value = self.dwd_weather.weather_codes[item][0] else: @@ -214,204 +237,109 @@ def get_condition_hourly(self): data.append({ATTR_FORECAST_TIME: key, "value": value}) return data - def get_temperature_hourly(self): + def get_hourly(self, data_type: WeatherDataType): data = [] + timestamp = datetime.now(timezone.utc) + timestamp = datetime( + timestamp.year, + timestamp.month, + timestamp.day, + timestamp.hour, + tzinfo=timezone.utc, + ) for key in self.dwd_weather.forecast_data: + if ( + datetime( + *(time.strptime(key, "%Y-%m-%dT%H:%M:%S.%fZ")[0:6]), + 0, + timezone.utc, + ) + < timestamp + ): + continue + item = self.dwd_weather.forecast_data[key] + value = item[data_type.value] + if value is not None: + if data_type == WeatherDataType.TEMPERATURE: + value = round(value - 273.1, 1) + elif data_type == WeatherDataType.DEWPOINT: + value = round(value - 273.1, 1) + elif data_type == WeatherDataType.PRESSURE: + value = round(value / 100, 1) + elif data_type == WeatherDataType.WIND_SPEED: + value = round(value, 1) + elif data_type == WeatherDataType.WIND_DIRECTION: + value = round(value, 0) + elif data_type == WeatherDataType.WIND_GUSTS: + value = round(value, 1) + elif data_type == WeatherDataType.PRECIPITATION: + value = round(value, 1) + elif data_type == WeatherDataType.PRECIPITATION_PROBABILITY: + value = round(value, 0) + elif data_type == WeatherDataType.PRECIPITATION_DURATION: + value = round(value, 1) + elif data_type == WeatherDataType.CLOUD_COVERAGE: + value = round(value, 0) + elif data_type == WeatherDataType.VISIBILITY: + value = round(value / 1000, 1) + elif data_type == WeatherDataType.SUN_DURATION: + value = round(value, 0) + elif data_type == WeatherDataType.SUN_IRRADIANCE: + value = round(value, 0) + elif data_type == WeatherDataType.FOG_PROBABILITY: + value = round(value, 0) + elif data_type == WeatherDataType.HUMIDITY: + value = round(value, 1) data.append( { ATTR_FORECAST_TIME: key, - "value": round( - item[dwdforecast.WeatherDataType.TEMPERATURE.value] - 273.1, 1 - ), + "value": value, } ) return data + def get_temperature_hourly(self): + return self.get_hourly(WeatherDataType.TEMPERATURE) + def get_dewpoint_hourly(self): - data = [] - for key in self.dwd_weather.forecast_data: - item = self.dwd_weather.forecast_data[key] - data.append( - { - ATTR_FORECAST_TIME: key, - "value": round( - item[dwdforecast.WeatherDataType.DEWPOINT.value] - 273.1, 1 - ), - } - ) - return data + return self.get_hourly(WeatherDataType.DEWPOINT) def get_pressure_hourly(self): - data = [] - for key in self.dwd_weather.forecast_data: - item = self.dwd_weather.forecast_data[key] - data.append( - { - ATTR_FORECAST_TIME: key, - "value": round( - item[dwdforecast.WeatherDataType.PRESSURE.value] / 100, 1 - ), - } - ) - return data + return self.get_hourly(WeatherDataType.PRESSURE) def get_wind_speed_hourly(self): - data = [] - for key in self.dwd_weather.forecast_data: - item = self.dwd_weather.forecast_data[key] - data.append( - { - ATTR_FORECAST_TIME: key, - "value": item[dwdforecast.WeatherDataType.WIND_SPEED.value], - } - ) - return data + return self.get_hourly(WeatherDataType.WIND_SPEED) def get_wind_direction_hourly(self): - data = [] - for key in self.dwd_weather.forecast_data: - item = self.dwd_weather.forecast_data[key] - data.append( - { - ATTR_FORECAST_TIME: key, - "value": item[dwdforecast.WeatherDataType.WIND_DIRECTION.value], - } - ) - return data + return self.get_hourly(WeatherDataType.WIND_DIRECTION) def get_wind_gusts_hourly(self): - data = [] - for key in self.dwd_weather.forecast_data: - item = self.dwd_weather.forecast_data[key] - data.append( - { - ATTR_FORECAST_TIME: key, - "value": item[dwdforecast.WeatherDataType.WIND_GUSTS.value], - } - ) - return data + return self.get_hourly(WeatherDataType.WIND_GUSTS) def get_precipitation_hourly(self): - data = [] - for key in self.dwd_weather.forecast_data: - item = self.dwd_weather.forecast_data[key] - data.append( - { - ATTR_FORECAST_TIME: key, - "value": item[dwdforecast.WeatherDataType.PRECIPITATION.value], - } - ) - return data + return self.get_hourly(WeatherDataType.PRECIPITATION) def get_precipitation_probability_hourly(self): - data = [] - for key in self.dwd_weather.forecast_data: - item = self.dwd_weather.forecast_data[key] - data.append( - { - ATTR_FORECAST_TIME: key, - "value": item[ - dwdforecast.WeatherDataType.PRECIPITATION_PROBABILITY.value - ], - } - ) - return data + return self.get_hourly(WeatherDataType.PRECIPITATION_PROBABILITY) def get_precipitation_duration_hourly(self): - data = [] - for key in self.dwd_weather.forecast_data: - item = self.dwd_weather.forecast_data[key] - data.append( - { - ATTR_FORECAST_TIME: key, - "value": item[ - dwdforecast.WeatherDataType.PRECIPITATION_DURATION.value - ], - } - ) - return data + return self.get_hourly(WeatherDataType.PRECIPITATION_DURATION) def get_cloud_coverage_hourly(self): - data = [] - for key in self.dwd_weather.forecast_data: - item = self.dwd_weather.forecast_data[key] - data.append( - { - ATTR_FORECAST_TIME: key, - "value": item[dwdforecast.WeatherDataType.CLOUD_COVERAGE.value], - } - ) - return data + return self.get_hourly(WeatherDataType.CLOUD_COVERAGE) def get_visibility_hourly(self): - data = [] - for key in self.dwd_weather.forecast_data: - item = self.dwd_weather.forecast_data[key] - data.append( - { - ATTR_FORECAST_TIME: key, - "value": round( - item[dwdforecast.WeatherDataType.VISIBILITY.value] / 1000, 1 - ), - } - ) - return data + return self.get_hourly(WeatherDataType.VISIBILITY) def get_sun_duration_hourly(self): - data = [] - for key in self.dwd_weather.forecast_data: - item = self.dwd_weather.forecast_data[key] - data.append( - { - ATTR_FORECAST_TIME: key, - "value": item[dwdforecast.WeatherDataType.SUN_DURATION.value], - } - ) - return data + return self.get_hourly(WeatherDataType.SUN_DURATION) def get_sun_irradiance_hourly(self): - data = [] - for key in self.dwd_weather.forecast_data: - item = self.dwd_weather.forecast_data[key] - data.append( - { - ATTR_FORECAST_TIME: key, - "value": item[dwdforecast.WeatherDataType.SUN_IRRADIANCE.value], - } - ) - return data + return self.get_hourly(WeatherDataType.SUN_IRRADIANCE) def get_fog_probability_hourly(self): - data = [] - for key in self.dwd_weather.forecast_data: - item = self.dwd_weather.forecast_data[key] - data.append( - { - ATTR_FORECAST_TIME: key, - "value": item[dwdforecast.WeatherDataType.FOG_PROBABILITY.value], - } - ) - return data + return self.get_hourly(WeatherDataType.FOG_PROBABILITY) def get_humidity_hourly(self): - data = [] - rh_c2 = 17.5043 - rh_c3 = 241.2 - - for key in self.dwd_weather.forecast_data: - T = ( - self.dwd_weather.forecast_data[key][ - dwdforecast.WeatherDataType.TEMPERATURE.value - ] - - 273.1 - ) - TD = ( - self.dwd_weather.forecast_data[key][ - dwdforecast.WeatherDataType.DEWPOINT.value - ] - - 273.1 - ) - RH = 100 * math.exp((rh_c2 * TD / (rh_c3 + TD)) - (rh_c2 * T / (rh_c3 + T))) - data.append({ATTR_FORECAST_TIME: key, "value": round(RH, 1)}) - return data + return self.get_hourly(WeatherDataType.HUMIDITY) diff --git a/custom_components/dwd_weather/const.py b/custom_components/dwd_weather/const.py index 84c209d..67ead63 100644 --- a/custom_components/dwd_weather/const.py +++ b/custom_components/dwd_weather/const.py @@ -10,7 +10,7 @@ ATTR_STATION_ID = "station_id" ATTR_STATION_NAME = "station_name" -DEFAULT_SCAN_INTERVAL = timedelta(minutes=15) +DEFAULT_SCAN_INTERVAL = timedelta(minutes=1) DWDWEATHER_DATA = "dwd_weather_data" DWDWEATHER_COORDINATOR = "dwd_weather_coordinator" diff --git a/custom_components/dwd_weather/manifest.json b/custom_components/dwd_weather/manifest.json index 30210ca..e086e91 100644 --- a/custom_components/dwd_weather/manifest.json +++ b/custom_components/dwd_weather/manifest.json @@ -1,6 +1,6 @@ { "domain": "dwd_weather", - "version": "1.2.6", + "version": "1.2.8", "name": "Deutscher Wetterdienst (DWD)", "documentation": "https://github.com/FL550/dwd_weather", "issue_tracker": "https://github.com/FL550/dwd_weather/issues", @@ -9,5 +9,5 @@ "codeowners": [ "@FL550" ], - "requirements": ["simple_dwd_weatherforecast==1.0.10"] + "requirements": ["simple_dwd_weatherforecast==1.0.12"] } diff --git a/custom_components/dwd_weather/sensor.py b/custom_components/dwd_weather/sensor.py index 52c1d44..60b834c 100644 --- a/custom_components/dwd_weather/sensor.py +++ b/custom_components/dwd_weather/sensor.py @@ -11,8 +11,6 @@ LENGTH_KILOMETERS, PRESSURE_HPA, SPEED_METERS_PER_SECOND, - STATE_OK, - STATE_UNAVAILABLE, TEMP_CELSIUS, TIME_SECONDS, ) @@ -154,9 +152,40 @@ def unique_id(self): @property def state(self): """Return the state of the sensor.""" - if self._connector.latest_update: - return STATE_OK - return STATE_UNAVAILABLE + result = "" + if self._type == "weather": + result = self._connector.get_condition() + elif self._type == "temperature": + result = self._connector.get_temperature() + elif self._type == "dewpoint": + result = self._connector.get_dewpoint() + elif self._type == "pressure": + result = self._connector.get_pressure() + elif self._type == "wind_speed": + result = self._connector.get_wind_speed() + elif self._type == "wind_direction": + result = self._connector.get_wind_direction() + elif self._type == "wind_gusts": + result = self._connector.get_wind_gusts() + elif self._type == "precipitation": + result = self._connector.get_precipitation() + elif self._type == "precipitation_probability": + result = self._connector.get_precipitation_probability() + elif self._type == "precipitation_duration": + result = self._connector.get_precipitation_duration() + elif self._type == "cloud_coverage": + result = self._connector.get_cloud_coverage() + elif self._type == "visibility": + result = self._connector.get_visibility() + elif self._type == "sun_duration": + result = self._connector.get_sun_duration() + elif self._type == "sun_irradiance": + result = self._connector.get_sun_irradiance() + elif self._type == "fog_probability": + result = self._connector.get_fog_probability() + elif self._type == "humidity": + result = self._connector.get_humidity() + return result @property def unit_of_measurement(self): From c95079720d6ac82dd916511c632f42101a99e816 Mon Sep 17 00:00:00 2001 From: eifinger Date: Sun, 11 Apr 2021 22:02:09 +0200 Subject: [PATCH 2/2] chore: bump 2021.4.3 --- .github/workflows/homeassistant-installed.yaml | 2 +- README.md | 2 +- www/plantuml/homeassistant-architecture.puml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/homeassistant-installed.yaml b/.github/workflows/homeassistant-installed.yaml index 76e0f9e..1ca147a 100644 --- a/.github/workflows/homeassistant-installed.yaml +++ b/.github/workflows/homeassistant-installed.yaml @@ -34,6 +34,6 @@ jobs: - name: Create secrets.yaml run: mv travis_secrets.yaml secrets.yaml - name: Home Assistant Check Installed - uses: "docker://homeassistant/home-assistant:2021.3.4" + uses: "docker://homeassistant/home-assistant:2021.4.3" with: args: python -m homeassistant --config . --script check_config --info all diff --git a/README.md b/README.md index 23c5b9d..c51493e 100644 --- a/README.md +++ b/README.md @@ -412,7 +412,7 @@ version: '2.1' services: homeassistant: container_name: homeassistant - image: homeassistant/home-assistant:2021.3.4 + image: homeassistant/home-assistant:2021.4.3 volumes: - /home/admin/homeassistant:/config - /etc/localtime:/etc/localtime:ro diff --git a/www/plantuml/homeassistant-architecture.puml b/www/plantuml/homeassistant-architecture.puml index 86b01ca..b1f7da5 100644 --- a/www/plantuml/homeassistant-architecture.puml +++ b/www/plantuml/homeassistant-architecture.puml @@ -5,7 +5,7 @@ LAYOUT_LEFT_RIGHT package "HP Microserver Gen10" { - Container(homeassistant, "homeassistant/home-assistant:2021.3.4", "Homeassistant") + Container(homeassistant, "homeassistant/home-assistant:2021.4.3", "Homeassistant") Container(find3, "https://github.com/schollz/find3", "FIND3") Container(mqtt, "eclipse-mosquitto:latest", "Mosquitto") Container(facerec_service, "eifinger/face_recognition:latest", "Facerecognition")