meteocat 3.1.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +45 -45
  2. package/.github/ISSUE_TEMPLATE/config.yml +8 -8
  3. package/.github/ISSUE_TEMPLATE/improvement.md +39 -39
  4. package/.github/ISSUE_TEMPLATE/new_function.md +41 -41
  5. package/.github/labels.yml +63 -63
  6. package/.github/workflows/autocloser.yaml +27 -27
  7. package/.github/workflows/close-on-label.yml +48 -48
  8. package/.github/workflows/force-sync-labels.yml +18 -18
  9. package/.github/workflows/hassfest.yaml +13 -13
  10. package/.github/workflows/publish-zip.yml +67 -67
  11. package/.github/workflows/release.yml +41 -41
  12. package/.github/workflows/stale.yml +63 -63
  13. package/.github/workflows/sync-gitlab.yml +107 -107
  14. package/.github/workflows/sync-labels.yml +21 -21
  15. package/.github/workflows/validate.yaml +16 -16
  16. package/.pre-commit-config.yaml +37 -37
  17. package/.releaserc +37 -37
  18. package/AUTHORS.md +13 -13
  19. package/CHANGELOG.md +954 -898
  20. package/README.md +207 -204
  21. package/conftest.py +11 -11
  22. package/custom_components/meteocat/__init__.py +298 -293
  23. package/custom_components/meteocat/condition.py +63 -59
  24. package/custom_components/meteocat/config_flow.py +613 -435
  25. package/custom_components/meteocat/const.py +132 -120
  26. package/custom_components/meteocat/coordinator.py +1040 -205
  27. package/custom_components/meteocat/helpers.py +58 -63
  28. package/custom_components/meteocat/manifest.json +25 -24
  29. package/custom_components/meteocat/options_flow.py +287 -277
  30. package/custom_components/meteocat/sensor.py +366 -4
  31. package/custom_components/meteocat/strings.json +1058 -867
  32. package/custom_components/meteocat/translations/ca.json +1058 -867
  33. package/custom_components/meteocat/translations/en.json +1058 -867
  34. package/custom_components/meteocat/translations/es.json +1058 -867
  35. package/custom_components/meteocat/version.py +1 -1
  36. package/custom_components/meteocat/weather.py +218 -218
  37. package/filetree.py +48 -48
  38. package/filetree.txt +79 -70
  39. package/hacs.json +8 -8
  40. package/images/daily_forecast_2_alerts.png +0 -0
  41. package/images/daily_forecast_no_alerts.png +0 -0
  42. package/images/diagnostic_sensors.png +0 -0
  43. package/images/dynamic_sensors.png +0 -0
  44. package/images/options.png +0 -0
  45. package/images/regenerate_assets.png +0 -0
  46. package/images/setup_options.png +0 -0
  47. package/images/system_options.png +0 -0
  48. package/info.md +11 -11
  49. package/package.json +22 -22
  50. package/poetry.lock +3222 -3222
  51. package/pyproject.toml +68 -68
  52. package/requirements.test.txt +3 -3
  53. package/setup.cfg +64 -64
  54. package/setup.py +10 -10
  55. package/tests/bandit.yaml +17 -17
  56. package/tests/conftest.py +19 -19
  57. package/tests/test_init.py +9 -9
@@ -1,63 +1,58 @@
1
- from __future__ import annotations
2
-
3
- import logging
4
- from datetime import datetime
5
- from pathlib import Path
6
- from homeassistant.core import HomeAssistant
7
- from homeassistant.util.dt import as_local, as_utc, start_of_local_day
8
- from homeassistant.helpers.sun import get_astral_event_date
9
-
10
- _LOGGER = logging.getLogger(__name__)
11
-
12
- # Ruta base para guardar archivos persistentes que se descargan de la API y que son utilizados por los coordinadores
13
- def get_storage_dir(hass: HomeAssistant, subdir: str | None = None) -> Path:
14
- """Devuelve una ruta persistente en config/meteocat_files[/subdir]."""
15
- base_dir = Path(hass.config.path("meteocat_files"))
16
- if subdir:
17
- base_dir = base_dir / subdir
18
- base_dir.mkdir(parents=True, exist_ok=True)
19
- return base_dir
20
-
21
- # Cálculo de amanecer y atardecer para definir cuando es de noche
22
- def get_sun_times(hass, current_time=None):
23
- """Obtén las horas de amanecer y atardecer para el día actual."""
24
- if current_time is None:
25
- current_time = datetime.now()
26
-
27
- # Asegúrate de que current_time es aware (UTC)
28
- current_time = as_utc(current_time)
29
- today = start_of_local_day(as_local(current_time))
30
-
31
- # Obtén los eventos de amanecer y atardecer del día actual
32
- sunrise = get_astral_event_date(hass, "sunrise", today)
33
- sunset = get_astral_event_date(hass, "sunset", today)
34
-
35
- _LOGGER.debug(
36
- "Sunrise: %s, Sunset: %s, Current Time: %s",
37
- sunrise,
38
- sunset,
39
- as_local(current_time),
40
- )
41
-
42
- if sunrise and sunset:
43
- return sunrise, sunset
44
-
45
- raise ValueError("No se pudieron determinar los datos de amanecer y atardecer.")
46
-
47
- def is_night(current_time, hass):
48
- """Determina si actualmente es de noche."""
49
- # Asegúrate de que current_time es aware (UTC)
50
- if current_time.tzinfo is None:
51
- current_time = as_utc(current_time)
52
-
53
- sunrise, sunset = get_sun_times(hass, current_time)
54
-
55
- _LOGGER.debug(
56
- "Hora actual: %s, Amanecer: %s, Atardecer: %s",
57
- as_local(current_time),
58
- as_local(sunrise),
59
- as_local(sunset),
60
- )
61
-
62
- # Es de noche si es antes del amanecer o después del atardecer
63
- return current_time < sunrise or current_time > sunset
1
+ from __future__ import annotations
2
+
3
+ import logging
4
+ from datetime import datetime
5
+ from pathlib import Path
6
+ from homeassistant.core import HomeAssistant
7
+ from homeassistant.util import dt as dt_util
8
+ from solarmoonpy.location import Location
9
+
10
+ _LOGGER = logging.getLogger(__name__)
11
+
12
+ # Ruta base para guardar archivos persistentes que se descargan de la API y que son utilizados por los coordinadores
13
+ def get_storage_dir(hass: HomeAssistant, subdir: str | None = None) -> Path:
14
+ """Devuelve una ruta persistente en config/meteocat_files[/subdir]."""
15
+ base_dir = Path(hass.config.path("meteocat_files"))
16
+ if subdir:
17
+ base_dir = base_dir / subdir
18
+ base_dir.mkdir(parents=True, exist_ok=True)
19
+ return base_dir
20
+
21
+ # Cálculo de amanecer y atardecer para definir cuando es de noche
22
+ def get_sun_times(location: Location, current_time: datetime | None = None) -> tuple[datetime, datetime]:
23
+ """Obtiene las horas de amanecer y atardecer para una ubicación usando solarmoonpy."""
24
+ now = dt_util.as_local(current_time or dt_util.now())
25
+ today = now.date()
26
+ sunrise = location.sunrise(date=today, local=True)
27
+ sunset = location.sunset(date=today, local=True)
28
+
29
+ if not sunrise or not sunset:
30
+ raise ValueError("No se pudieron calcular amanecer o atardecer.")
31
+
32
+ _LOGGER.debug(
33
+ "[solarmoonpy] Amanecer: %s, Atardecer: %s, Hora actual: %s",
34
+ sunrise, sunset, now
35
+ )
36
+ return sunrise, sunset
37
+
38
+ def is_night(current_time, location: Location) -> bool:
39
+ """Determina si actualmente es de noche usando una instancia de Location."""
40
+ # Asegurarse de que current_time sea aware y en zona local
41
+ if current_time.tzinfo is None:
42
+ _LOGGER.warning("current_time sin zona horaria, asumiendo UTC")
43
+ current_time = dt_util.as_local(dt_util.utc_to_local(current_time))
44
+ else:
45
+ current_time = dt_util.as_local(current_time)
46
+
47
+ try:
48
+ sunrise, sunset = get_sun_times(location, current_time)
49
+ except Exception as e:
50
+ _LOGGER.warning("Fallo al calcular amanecer/atardecer con solarmoonpy: %s", e)
51
+ return False # fallback seguro
52
+
53
+ is_night_now = current_time < sunrise or current_time > sunset
54
+ _LOGGER.debug(
55
+ "[solarmoonpy] Hora actual: %s | Amanecer: %s | Atardecer: %s → Noche: %s",
56
+ current_time, sunrise, sunset, is_night_now
57
+ )
58
+ return is_night_now
@@ -1,24 +1,25 @@
1
- {
2
- "domain": "meteocat",
3
- "name": "Meteocat",
4
- "codeowners": [
5
- "@figorr"
6
- ],
7
- "config_flow": true,
8
- "dependencies": [
9
- "persistent_notification",
10
- "http"
11
- ],
12
- "documentation": "https://github.com/figorr/meteocat",
13
- "iot_class": "cloud_polling",
14
- "issue_tracker": "https://github.com/figorr/meteocat/issues",
15
- "loggers": [
16
- "meteocatpy"
17
- ],
18
- "requirements": [
19
- "meteocatpy==1.0.1",
20
- "packaging>=20.3",
21
- "wrapt>=1.14.0"
22
- ],
23
- "version": "3.1.0"
24
- }
1
+ {
2
+ "domain": "meteocat",
3
+ "name": "Meteocat",
4
+ "codeowners": [
5
+ "@figorr"
6
+ ],
7
+ "config_flow": true,
8
+ "dependencies": [
9
+ "persistent_notification",
10
+ "http"
11
+ ],
12
+ "documentation": "https://github.com/figorr/meteocat",
13
+ "iot_class": "cloud_polling",
14
+ "issue_tracker": "https://github.com/figorr/meteocat/issues",
15
+ "loggers": [
16
+ "meteocatpy"
17
+ ],
18
+ "requirements": [
19
+ "meteocatpy==1.0.2",
20
+ "solarmoonpy==1.0.8",
21
+ "packaging>=20.3",
22
+ "wrapt>=1.14.0"
23
+ ],
24
+ "version": "4.0.0"
25
+ }