Limych/ha-gismeteo

Frequently become Unavailable

Masterz69 opened this issue · 28 comments

Environment

System Health

version core-2021.7.3
installation_type Home Assistant OS
dev false
hassio true
docker true
virtualenv false
python_version 3.9.5
os_name Linux
os_version 5.10.17-v8
arch aarch64
timezone Europe/Riga
Home Assistant Community Store
GitHub API ok
Github API Calls Remaining 4876
Installed Version 1.13.2
Stage running
Available Repositories 912
Installed Repositories 20
Home Assistant Cloud
logged_in false
can_reach_cert_server ok
can_reach_cloud_auth ok
can_reach_cloud pending
Home Assistant Supervisor
host_os Home Assistant OS 6.1
update_channel stable
supervisor_version supervisor-2021.06.8
docker_version 20.10.6
disk_total 54.3 GB
disk_used 13.5 GB
healthy true
supported true
board rpi4-64
supervisor_api ok
version_api ok
installed_addons Samba Backup (4.5.0), SSH & Web Terminal (9.0.0), File editor (5.3.3), Mosquitto broker (5.1.1), Z-Wave JS to MQTT (0.23.2), Zigbee2mqtt (1.18.2-1), MariaDB (2.4.0), phpMyAdmin (0.4.3), Samba share (9.5.0)
Lovelace
dashboards 8
resources 8
views 29
mode storage

Describe the bug

As far as I noticed - after core upgrade to 2021.7.x Gismeteo intergration entities frequently (several times par day) become unavailable. But not sure this (HA core version) is a reason.

Configuration.yaml

Add your configs here if any.

Steps to Reproduce

Expected behavior

Debug log


2021-07-27 15:50:20 ERROR (MainThread) [custom_components.gismeteo] Error fetching gismeteo data: Can't update weather data! Invalid server response.

Additional context

After integration restart it starts to show data.

Same bug

тоже самое, перестает работать после нескольких часов. ограничение API?

fufar commented

Так же переодически выскакивает

У меня совсем перестало работать. Рестарт ХА не помогает.

Аналогично, через пару часов отваливается, после рестарта интеграции снова включается.

У меня все ломается когда в ответ на запрос местополжения в async_get_location приходит такое:

<?xml version="1.0" encoding="utf-8"?><document><html>
<head><title>502 Bad Gateway</title></head>
<body bgcolor="white">
<center><h1>502 Bad Gateway</h1></center>
<hr><center>openresty</center>
</body>
</html>
</document>

Такая же проблема. После перезагрузки сервера работоспособность восстанавливается.
1 ошибка в журнале сервера:

Эта ошибка возникла в кастомной интеграции.
Logger: custom_components.gismeteo
Source: helpers/update_coordinator.py:193
Integration: Gismeteo (documentation, issues)
First occurred: 21:00:57 (1 occurrences)
Last logged: 21:00:57
Timeout fetching gismeteo data

2 ошибка:
Эта ошибка возникла в кастомной интеграции.
Logger: custom_components.gismeteo
Source: helpers/update_coordinator.py:219
Integration: Gismeteo (documentation, issues)
First occurred: 21:45:57 (1 occurrences)
Last logged: 21:45:57
Error fetching gismeteo data: Can't update weather data! Invalid server response.

the same

аналогично

Ситуация ухудшается

Это ошибки на стороне ГисМетео. Они возвращают XML с ошибкой 5XX.
Проблему можно было бы решить скачивая сначала во временный файл, и после, если он корректный переименовывая его. Но непонятно тогда как поступить если API будет очень долго не возвращать ничего полезного? Тогда у нас застрянет устаревший прогноз.

@vegetate7, не всегда это происходит при обновлении прогноза. У меня, например, интеграция отваливается целиком если при старте прилетает bad gateway при попытке определения местоположения #68 (comment) (его, кстати, можно кэшировать и если не получилось получить от gismeteo использовать значение из кэша: HA не так часто куда-то переезжает).

уточните, это не из-за того, что мы слишком часто запрашиваем данные у АПИ гисметео, это из-за некорректной логики в интеграции?

есть решение?

The same problem...

The same problem... we are waiting for a solution to the problem...

iksrd commented

I have the same problem... I am waiting for a solution to this problem...

Господа,

К сожалению, причина в перриодической недоступности данных находится на стороне Гисметео.

Для исключения перегрузок сервиса и блокирования доступа с самой первой версии данного модуля в него встроена система кэширования запросов. Модуль не может создать такой нагрузки, чтобы вы получили бан. Даже если вас будет много.

Повлиять на работу сервером Гисметео я не имею никакой возможности. Обращать внимание техподдержки Гисметео на проблему ОПАСНО, т.к. данный модуль фактически использует недокументированную возможности системы для бесплатного доступа к данным, которые Гисметео пытается ПРОДАВАТЬ.

В сложившейся ситуации нам с Вами остаётся только ждать, когда техподдержка Гисметео сама заметит проблему и исправит её.

@Limych спасибо за разъяснения. Но почему при отсутствии ответа от Гисметео не показывается старый прогноз, а ошибка?

@Limych может тогда все-же сохранять старые данные, пока новые не будут получены полностью?
Ну, скажем, в течении 1 часа. Это не совсем кеш, другая логика - патемся получить свежие данные, и если неудачно - показываем старые. Если старые больше "времени хранения" - тогда уже показывать ошибки. Чтобы можно было заметить, если что-то совсем сломалось.

@vegetate7,
Попробую сделать такую логику, когда время будет...

Главное - фиксировать время последней актуализации данных (last-updated), чтобы было понятно, насколько данные свежие

Желающие тестируют новую логику кэширования:
https://github.com/Limych/ha-gismeteo/releases/tag/2.3.5-beta

Опубликовано как бета, т.к. не уверен пока в безошибочности кода.

Максимальные сроки кэширования установлены в неделю для локаций и 3 часа для прогнозов.

UPD. Уже увидел первый баг: last_updated выдаёт как timestamp. Исправлю чуть позже.

UPD. Уже увидел первый баг: last_updated выдаёт как timestamp. Исправлю чуть позже.

Взял из dev ветки. Вроде работает, но появилась новая проблема.
Сконфигурировано два сенсора, daily и hourly. Один из них не апдейтится. Порядок расположения в configuration.yaml неважен, может не апдетить один, а после перезагрузки не апдейтит другой:
В 6:47 была перезагрузка.
Screenshot_20220107_071906

Screenshot_20220107_071926

@vegetate7,
Логи! Дебаг-логи на стол, пожалуйста!
Без них любые заявления для меня не имеют смысла.

Ок, с логом (и картинками).
Теперь не обновился часовой сенсор. Понаблюдал внимательнее, какой из сенсоров будет обновляться - не зависит от перезагрузки. Просто иногда обновляется часовой, иногда дневной. А иногда и оба. Закономерность не нашел. Можно было бы конечно и так оставить, но боюсь это указывает на какую-то проблему, которая может в другом месте вылезти.

Screenshot_20220107_165153

Screenshot_20220107_165126

Лог:
home-assistant.log

По логу видно, что когда приходит время обновить кеш - оба сенсора скачивают с гисметео одновременно.

вот. Я его наконец-то поймал. Добавил размер контента в месте где логгится результат запроса, и все стало видно.
Собственно прям в конце лога:

2022-01-10 22:49:19 DEBUG (MainThread) [custom_components.gismeteo.api] Data retrieved from https://services.gismeteo.ru/inform-service/inf_chrome/forecast/?city=4578&lang=en, status: 200, size: 228
2022-01-10 22:49:19 DEBUG (MainThread) [custom_components.gismeteo.cache] Store cache file /config/.storage/forecast_4578.xml

Смысл в том ,что опозновать правильный ли пришел ответ от сервера только по HTTPStatus - не получится.
В данном случае мы получили XML c 502 Bad Gateway но HTTP статус все равно 200. и этот "плохой" ответ мы и записали в кеш в _async_get_data.

Нужно попробовать декодировать перед self._cache.save_cache(cache_fname, data) и сохранять только если найден какой-нибудь обязательный элемент.

home-assistant.gismeteo.log

Примерно так можно решить проблему.
Внимание, нет никакой защиты от сильно устаревших данных (если что-то совсем испортится, будет просто продолжать показывать старый прогноз)
Я не очень силен в питоне.

diff -urb gismeteo/api.py gismeteo.xmlfix/api.py
--- gismeteo/api.py	2022-01-07 05:25:24.256879150 +0600
+++ gismeteo.xmlfix/api.py	2022-01-11 20:25:02.651523711 +0600
@@ -193,10 +193,17 @@
                 if resp.status != HTTPStatus.OK:
                     _LOGGER.error("Invalid response from Gismeteo API: %s", resp.status)
                 else:
+                    data = await resp.text()
                     _LOGGER.debug(
-                        "Data retrieved from %s, status: %s", url, resp.status
+                        "Data retrieved from %s, status: %s, size: %d", url, resp.status, len(data)
+                    )
+                    try:
+                        xml = etree.fromstring(data)
+                    except (etree.ParseError, TypeError, AttributeError) as ex:
+                        data = None
+                        _LOGGER.debug(
+                            "Data retrieved from %s, is invalid", url
                     )
-                    data = await resp.text()
 
         if not data and data_cached:
             _LOGGER.debug("Cached response used")