meteocat 3.1.0 → 3.2.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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,37 @@
1
+ # [3.2.0](https://github.com/figorr/meteocat/compare/v3.1.0...v3.2.0) (2025-11-07)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * add validation date for moon coordinator ([8644f56](https://github.com/figorr/meteocat/commit/8644f56d8f8b6b607ba8809499afbfb81eb70b28))
7
+ * adjust moon update interval ([ea51d90](https://github.com/figorr/meteocat/commit/ea51d905a232ab947607333ea4abaf449cd2e786))
8
+ * fix friendly time translation ([9081a34](https://github.com/figorr/meteocat/commit/9081a343fd1562cb001f8a4b69948be3e26cbe00))
9
+ * fix reset data moon file coordinator ([f3cf22f](https://github.com/figorr/meteocat/commit/f3cf22f1fb1d1a19d6ee9fefd2be304850be1180))
10
+ * more accurate moon calculation ([dcee6e0](https://github.com/figorr/meteocat/commit/dcee6e0040d1cf77860fc7cbd06a5518145d3a72))
11
+
12
+
13
+ ### Features
14
+
15
+ * add new moon day data ([77edf68](https://github.com/figorr/meteocat/commit/77edf681af037f00748b2b3cf2d281655d225718))
16
+ * add new moon day data ([d2be96e](https://github.com/figorr/meteocat/commit/d2be96ec7f4f9d48c1f018ba2c642f29558d05fe))
17
+ * add translations for lunation attribute ([10e3409](https://github.com/figorr/meteocat/commit/10e3409f82fa6530f0edf81c5e8406d019aeeaf1))
18
+ * bump solarmoonpy to v1.0.0 ([65c2a04](https://github.com/figorr/meteocat/commit/65c2a0495250bac284c060b575256f95f4fb0be0))
19
+ * bump solarmoonpy to v1.0.1 ([aa86747](https://github.com/figorr/meteocat/commit/aa86747ed41d69a80ac009b75b596746762548fe))
20
+ * bump solarmoonpy to v1.0.3 ([246bd83](https://github.com/figorr/meteocat/commit/246bd835589978940efc11722b79e420f838ecab))
21
+ * include latitude, longitude and altitude as new required variables ([5ef864c](https://github.com/figorr/meteocat/commit/5ef864ca38fa17ed05b36a19a96b8c7182f66be7))
22
+ * new latitude, longitude and altitude update options setup ([1aeb968](https://github.com/figorr/meteocat/commit/1aeb9682c8e65b3cb0b29a7b7467edcc455304c9))
23
+ * new lunation attribute for moon and moon phase name code ([60c7129](https://github.com/figorr/meteocat/commit/60c7129757916908baf26439819458ea3a173ad4))
24
+ * new lunation attribute for moon sensor ([9bb32ff](https://github.com/figorr/meteocat/commit/9bb32ff03bd7eba291a1ee1aa578e2838dcf9bd5))
25
+ * new lunation data and moon phase name rework ([0616401](https://github.com/figorr/meteocat/commit/0616401243334c21736d0877e5e50e435279e002))
26
+ * new moon day attribute ([86ec6e3](https://github.com/figorr/meteocat/commit/86ec6e311fc098174027f17d3502e8be740d7e86))
27
+ * new moon sensors ([7c7c1d3](https://github.com/figorr/meteocat/commit/7c7c1d38393a40fd2e69eeba2c24bb185ae349ef))
28
+ * new solarmoonpy requirement for sun and moon events calculation ([1d25a62](https://github.com/figorr/meteocat/commit/1d25a6252cf568e1242f654c389aeada2b5d73f6))
29
+ * new sun and moon coordinators ([af2290e](https://github.com/figorr/meteocat/commit/af2290e7384a9ad5416afdf4d6767ad69099813c))
30
+ * new sun and moon files ([b489d7a](https://github.com/figorr/meteocat/commit/b489d7a9abc5af747fc50a2e0d7b0d661408b824))
31
+ * new sun and moon sensors ([91265f3](https://github.com/figorr/meteocat/commit/91265f3c6cbd512b3706c29d466f9bb01df6d45e))
32
+ * translation for new moon day attribute ([162859e](https://github.com/figorr/meteocat/commit/162859e2822374b81835cb1af07325dceaf5a55e))
33
+ * translations for the new moon and sun sensors ([91a33b6](https://github.com/figorr/meteocat/commit/91a33b6b52e34ed69eed4eb5fbfaf9dffd20df57))
34
+
1
35
  # [3.1.0](https://github.com/figorr/meteocat/compare/v3.0.0...v3.1.0) (2025-09-27)
2
36
 
3
37
 
package/README.md CHANGED
@@ -135,6 +135,9 @@ You will see three available options:
135
135
  If for any reason some files in the `assets` folder (`towns.json`, `stations.json`, `variables.json`, `symbols.json`, or `stations_<town_id>.json`) are missing or outdated, you can regenerate them directly from the options menu.
136
136
  > ℹ️ If the Meteocat API is not available at that moment, the integration will still start, and you can retry regeneration later.
137
137
 
138
+ - **Update coordinates and elevation**
139
+ Change the default station coordinates and elevation that were set during the first setup. So you can use your location coordinates and elevation for more accurate sun and moon data.
140
+
138
141
  ### Accessing the Options Menu
139
142
 
140
143
  You can access the Options Menu in two ways, both inside the integration:
@@ -168,7 +171,7 @@ Meteocat integration has its own weather card.
168
171
 
169
172
  To install the card, please follow the instructions from its own repository, [🎫 Meteocat Card](https://github.com/figorr/meteocat-card).
170
173
 
171
- ![Meteocat Card](images/daily_forecast_2_alerts.png)
174
+ ![Meteocat Card](images/daily_forecast_no_alerts.png)
172
175
 
173
176
  # Documentation
174
177
 
@@ -24,7 +24,7 @@ from .const import DOMAIN, PLATFORMS
24
24
  _LOGGER = logging.getLogger(__name__)
25
25
 
26
26
  # Versión
27
- __version__ = "3.1.0"
27
+ __version__ = "3.2.0"
28
28
 
29
29
  # Definir el esquema de configuración CONFIG_SCHEMA
30
30
  CONFIG_SCHEMA = vol.Schema(
@@ -44,6 +44,7 @@ CONFIG_SCHEMA = vol.Schema(
44
44
  vol.Optional("region_id"): cv.string,
45
45
  vol.Required("latitude"): cv.latitude,
46
46
  vol.Required("longitude"): cv.longitude,
47
+ vol.Required("altitude"): vol.Coerce(float),
47
48
  }
48
49
  )
49
50
  },
@@ -120,7 +121,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
120
121
  required_fields = [
121
122
  "api_key", "town_name", "town_id", "variable_name",
122
123
  "variable_id", "station_name", "station_id", "province_name",
123
- "province_id", "region_name", "region_id", "latitude", "longitude"
124
+ "province_id", "region_name", "region_id", "latitude", "longitude", "altitude"
124
125
  ]
125
126
  missing_fields = [field for field in required_fields if field not in entry_data]
126
127
  if missing_fields:
@@ -156,6 +157,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
156
157
  f"Provincia '{entry_data['province_name']}' (ID: {entry_data['province_id']}), "
157
158
  f"Comarca '{entry_data['region_name']}' (ID: {entry_data['region_id']}), "
158
159
  f"Coordenadas: ({entry_data['latitude']}, {entry_data['longitude']})."
160
+ f"Altitud: ({entry_data['altitude']})."
159
161
  )
160
162
 
161
163
  # Lista de coordinadores con sus clases
@@ -177,6 +179,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
177
179
  ("lightning_file_coordinator", "MeteocatLightningFileCoordinator"),
178
180
  ("sun_coordinator", "MeteocatSunCoordinator"),
179
181
  ("sun_file_coordinator", "MeteocatSunFileCoordinator"),
182
+ ("moon_coordinator", "MeteocatMoonCoordinator"),
183
+ ("moon_file_coordinator", "MeteocatMoonFileCoordinator"),
180
184
  ]
181
185
 
182
186
  hass.data.setdefault(DOMAIN, {})
@@ -261,6 +265,7 @@ async def async_remove_entry(hass: HomeAssistant, entry: ConfigEntry) -> None:
261
265
  files_folder / f"forecast_{town_id.lower()}_hourly_data.json",
262
266
  files_folder / f"forecast_{town_id.lower()}_daily_data.json",
263
267
  files_folder / f"sun_{town_id.lower()}_data.json",
268
+ files_folder / f"moon_{town_id.lower()}_data.json",
264
269
  ])
265
270
 
266
271
  # 3. Archivos de comarca (region_id)
@@ -290,4 +295,4 @@ async def async_remove_entry(hass: HomeAssistant, entry: ConfigEntry) -> None:
290
295
 
291
296
  # Intentar eliminar carpetas vacías
292
297
  for folder in [assets_folder, files_folder, base_folder]:
293
- safe_remove(folder, is_folder=True)
298
+ safe_remove(folder, is_folder=True)
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from datetime import datetime
4
+ from typing import Any
4
5
  from .const import CONDITION_MAPPING
5
6
  from .helpers import is_night
6
7
  import logging
@@ -8,7 +9,10 @@ import logging
8
9
  _LOGGER = logging.getLogger(__name__)
9
10
 
10
11
  def get_condition_from_statcel(
11
- codi_estatcel, current_time: datetime, hass, is_hourly: bool = True
12
+ codi_estatcel: Any,
13
+ current_time: datetime,
14
+ location,
15
+ is_hourly: bool = True
12
16
  ) -> dict:
13
17
  """
14
18
  Convierte el código 'estatCel' en condición de Home Assistant.
@@ -33,7 +37,7 @@ def get_condition_from_statcel(
33
37
  codi_estatcel = [codi_estatcel]
34
38
 
35
39
  # Determinar si es de noche
36
- is_night_flag = is_night(current_time, hass)
40
+ is_night_flag = is_night(current_time, location)
37
41
 
38
42
  # Identificar la condición basada en el código
39
43
  for condition, codes in CONDITION_MAPPING.items():
@@ -5,15 +5,25 @@ import json
5
5
  import logging
6
6
  from pathlib import Path
7
7
  from typing import Any
8
- from datetime import datetime, timezone
8
+ from datetime import date, datetime, timezone, timedelta
9
9
  from zoneinfo import ZoneInfo
10
10
 
11
11
  import voluptuous as vol
12
12
  import aiofiles
13
13
  import unicodedata
14
14
 
15
- from astral import LocationInfo
16
- from astral.sun import sun
15
+ from solarmoonpy.location import Location, LocationInfo
16
+ from solarmoonpy.moon import (
17
+ moon_phase,
18
+ moon_day,
19
+ moon_rise_set,
20
+ illuminated_percentage,
21
+ moon_distance,
22
+ moon_angular_diameter,
23
+ lunation_number,
24
+ get_moon_phase_name,
25
+ get_lunation_duration
26
+ )
17
27
  from homeassistant.config_entries import ConfigEntry, ConfigFlow, ConfigFlowResult
18
28
  from homeassistant.core import callback
19
29
  from homeassistant.exceptions import HomeAssistantError
@@ -90,6 +100,8 @@ class MeteocatConfigFlow(ConfigFlow, domain=DOMAIN):
90
100
  self.longitude: float | None = None
91
101
  self.altitude: float | None = None
92
102
  self.station_status: str | None = None
103
+ self.location: Location | None = None
104
+ self.timezone_str: str | None = None
93
105
 
94
106
  async def fetch_and_save_quotes(self, api_key: str):
95
107
  """Obtiene las cuotas de la API de Meteocat y las guarda en quotes.json."""
@@ -186,49 +198,214 @@ class MeteocatConfigFlow(ConfigFlow, domain=DOMAIN):
186
198
  )
187
199
 
188
200
  async def create_sun_file(self):
189
- """Crea el archivo sun_{town_id}_data.json con datos iniciales de sunrise y sunset."""
190
- if not self.selected_municipi or not self.latitude or not self.longitude:
201
+ """Crea el archivo sun_{town_id}_data.json con eventos solares + posición inicial del sol."""
202
+ if not self.selected_municipi or self.latitude is None or self.longitude is None:
191
203
  _LOGGER.warning("No se puede crear sun_{town_id}_data.json: faltan municipio o coordenadas")
192
204
  return
193
205
 
194
206
  town_id = self.selected_municipi["codi"]
195
207
  files_dir = get_storage_dir(self.hass, "files")
196
- sun_file = files_dir / f"sun_{town_id}_data.json"
208
+ sun_file = files_dir / f"sun_{town_id.lower()}_data.json"
197
209
 
198
- if not sun_file.exists():
199
- try:
200
- # Crear objeto LocationInfo con las coordenadas y zona horaria
201
- location = LocationInfo(
202
- name=self.selected_municipi["nom"],
203
- region="Catalonia",
204
- timezone="Europe/Madrid",
205
- latitude=self.latitude,
206
- longitude=self.longitude
207
- )
210
+ if sun_file.exists():
211
+ _LOGGER.debug("El archivo %s ya existe, no se crea de nuevo.", sun_file)
212
+ return
213
+
214
+ try:
215
+ # ZONA HORARIA DEL HASS
216
+ self.timezone_str = self.hass.config.time_zone or "Europe/Madrid"
217
+ tz = ZoneInfo(self.timezone_str)
218
+
219
+ # CREAR UBICACIÓN
220
+ self.location = Location(LocationInfo(
221
+ name=self.selected_municipi.get("nom", "Municipio"),
222
+ region="Spain",
223
+ timezone=self.timezone_str,
224
+ latitude=self.latitude,
225
+ longitude=self.longitude,
226
+ elevation=self.altitude or 0.0,
227
+ ))
228
+
229
+ now = datetime.now(tz)
230
+ today = now.date()
231
+ tomorrow = today + timedelta(days=1)
232
+
233
+ # EVENTOS HOY Y MAÑANA
234
+ events_today = self.location.sun_events(date=today, local=True)
235
+ events_tomorrow = self.location.sun_events(date=tomorrow, local=True)
236
+
237
+ # LÓGICA DE EVENTOS (igual que en el coordinador)
238
+ expected = {}
239
+ events_list = [
240
+ "dawn_astronomical", "dawn_nautical", "dawn_civil",
241
+ "sunrise", "noon", "sunset",
242
+ "dusk_civil", "dusk_nautical", "dusk_astronomical",
243
+ "midnight",
244
+ ]
245
+
246
+ for event in events_list:
247
+ event_time = events_today.get(event)
248
+ if event_time and now >= event_time:
249
+ expected[event] = events_tomorrow.get(event)
250
+ else:
251
+ expected[event] = event_time
252
+
253
+ # daylight_duration según sunrise
254
+ sunrise = expected["sunrise"]
255
+ expected["daylight_duration"] = (
256
+ events_tomorrow["daylight_duration"]
257
+ if sunrise == events_tomorrow["sunrise"]
258
+ else events_today["daylight_duration"]
259
+ )
260
+
261
+ # POSICIÓN ACTUAL DEL SOL
262
+ sun_pos = self.location.sun_position(dt=now, local=True)
263
+
264
+ # CONSTRUIR DADES
265
+ dades_dict = {
266
+ "dawn_civil": expected["dawn_civil"].isoformat() if expected["dawn_civil"] else None,
267
+ "dawn_nautical": expected["dawn_nautical"].isoformat() if expected["dawn_nautical"] else None,
268
+ "dawn_astronomical": expected["dawn_astronomical"].isoformat() if expected["dawn_astronomical"] else None,
269
+ "sunrise": expected["sunrise"].isoformat() if expected["sunrise"] else None,
270
+ "noon": expected["noon"].isoformat() if expected["noon"] else None,
271
+ "sunset": expected["sunset"].isoformat() if expected["sunset"] else None,
272
+ "dusk_civil": expected["dusk_civil"].isoformat() if expected["dusk_civil"] else None,
273
+ "dusk_nautical": expected["dusk_nautical"].isoformat() if expected["dusk_nautical"] else None,
274
+ "dusk_astronomical": expected["dusk_astronomical"].isoformat() if expected["dusk_astronomical"] else None,
275
+ "midnight": expected["midnight"].isoformat() if expected["midnight"] else None,
276
+ "daylight_duration": expected["daylight_duration"],
277
+
278
+ # CAMPOS DE POSICIÓN SOLAR
279
+ "sun_elevation": round(sun_pos["elevation"], 2),
280
+ "sun_azimuth": round(sun_pos["azimuth"], 2),
281
+ "sun_horizon_position": sun_pos["horizon_position"],
282
+ "sun_rising": sun_pos["rising"],
283
+ "sun_position_updated": now.isoformat(),
284
+ }
285
+
286
+ # JSON FINAL
287
+ data_with_timestamp = {
288
+ "actualitzat": {"dataUpdate": now.isoformat()},
289
+ "dades": [dades_dict],
290
+ }
208
291
 
209
- # Calcular sunrise y sunset para el día actual
292
+ # GUARDAR
293
+ sun_file.parent.mkdir(parents=True, exist_ok=True)
294
+ async with aiofiles.open(sun_file, "w", encoding="utf-8") as file:
295
+ await file.write(json.dumps(data_with_timestamp, ensure_ascii=False, indent=4))
296
+
297
+ _LOGGER.info(
298
+ "Archivo sun_%s_data.json creado con eventos + posición solar inicial (elev=%.2f°, az=%.2f°)",
299
+ town_id, sun_pos["elevation"], sun_pos["azimuth"]
300
+ )
301
+
302
+ except Exception as ex:
303
+ _LOGGER.error("Error al crear sun_%s_data.json: %s", town_id, ex)
304
+
305
+ async def create_moon_file(self):
306
+ """Crea el archivo moon_{town_id}_data.json con datos iniciales de la fase lunar, moonrise y moonset."""
307
+ if not self.selected_municipi or not self.latitude or not self.longitude:
308
+ _LOGGER.warning("No se puede crear moon_{town_id}_data.json: faltan municipio o coordenadas")
309
+ return
310
+
311
+ town_id = self.selected_municipi["codi"]
312
+ files_dir = get_storage_dir(self.hass, "files")
313
+ moon_file = files_dir / f"moon_{town_id}_data.json"
314
+
315
+ if not moon_file.exists():
316
+ try:
317
+ # Fecha actual en UTC
210
318
  current_time = datetime.now(timezone.utc).astimezone(TIMEZONE)
211
- sun_data = sun(location.observer, date=current_time.date(), tzinfo=TIMEZONE)
319
+ today = current_time.date()
320
+
321
+ # Inicializar parámetros con valores por defecto
322
+ phase = None
323
+ moon_day_today = None
324
+ lunation = None
325
+ illuminated = None
326
+ distance = None
327
+ angular_diameter = None
328
+ moon_phase_name = None
329
+ lunation_duration = None
330
+
331
+ # Calcular parámetros con manejo de errores individual
332
+ try:
333
+ phase = round(moon_phase(today), 2)
334
+ except Exception as ex:
335
+ _LOGGER.error("Error al calcular moon_phase: %s", ex)
336
+
337
+ try:
338
+ moon_day_today = moon_day(today)
339
+ except Exception as ex:
340
+ _LOGGER.error("Error al calcular moon_day: %s", ex)
341
+
342
+ try:
343
+ lunation = lunation_number(today)
344
+ except Exception as ex:
345
+ _LOGGER.error("Error al calcular lunation_number: %s", ex)
346
+
347
+ try:
348
+ illuminated = round(illuminated_percentage(today), 2)
349
+ except Exception as ex:
350
+ _LOGGER.error("Error al calcular illuminated_percentage: %s", ex)
351
+
352
+ try:
353
+ distance = round(moon_distance(today), 0)
354
+ except Exception as ex:
355
+ _LOGGER.error("Error al calcular moon_distance: %s", ex)
356
+
357
+ try:
358
+ angular_diameter = round(moon_angular_diameter(today), 2)
359
+ except Exception as ex:
360
+ _LOGGER.error("Error al calcular moon_angular_diameter: %s", ex)
361
+
362
+ try:
363
+ moon_phase_name = get_moon_phase_name(today)
364
+ except Exception as ex:
365
+ _LOGGER.error("Error al calcular moon_phase_name: %s", ex)
366
+
367
+ try:
368
+ lunation_duration = get_lunation_duration(today)
369
+ except Exception as ex:
370
+ _LOGGER.error("Error al calcular lunation_duration: %s", ex)
371
+
372
+ # Moonrise y moonset aproximados (UTC)
373
+ try:
374
+ rise_utc, set_utc = moon_rise_set(self.latitude, self.longitude, today)
375
+ rise_local = rise_utc.astimezone(TIMEZONE).isoformat() if rise_utc else None
376
+ set_local = set_utc.astimezone(TIMEZONE).isoformat() if set_utc else None
377
+ except Exception as ex:
378
+ _LOGGER.error("Error al calcular moon_rise_set: %s", ex)
379
+ rise_local = None
380
+ set_local = None
212
381
 
213
- # Formatear los datos para el archivo
214
- sun_data_formatted = {
382
+ # Formatear datos para guardar
383
+ moon_data_formatted = {
215
384
  "actualitzat": {"dataUpdate": current_time.isoformat()},
385
+ "last_lunar_update_date": today.isoformat(),
216
386
  "dades": [
217
387
  {
218
- "sunrise": sun_data["sunrise"].isoformat(),
219
- "sunset": sun_data["sunset"].isoformat(),
220
- "date": current_time.date().isoformat()
388
+ "moon_day": moon_day_today,
389
+ "moon_phase": phase,
390
+ "moon_phase_name": moon_phase_name,
391
+ "illuminated_percentage": illuminated,
392
+ "moon_distance": distance,
393
+ "moon_angular_diameter": angular_diameter,
394
+ "lunation": lunation,
395
+ "lunation_duration": lunation_duration,
396
+ "moonrise": rise_local,
397
+ "moonset": set_local
221
398
  }
222
399
  ]
223
400
  }
224
401
 
225
402
  # Guardar el archivo
226
- async with aiofiles.open(sun_file, "w", encoding="utf-8") as file:
227
- await file.write(json.dumps(sun_data_formatted, ensure_ascii=False, indent=4))
228
- _LOGGER.info("Archivo sun_%s_data.json creado con datos iniciales", town_id)
403
+ async with aiofiles.open(moon_file, "w", encoding="utf-8") as file:
404
+ await file.write(json.dumps(moon_data_formatted, ensure_ascii=False, indent=4))
405
+ _LOGGER.info("Archivo moon_%s_data.json creado con datos iniciales", town_id)
229
406
 
230
407
  except Exception as ex:
231
- _LOGGER.error("Error al crear sun_%s_data.json: %s", town_id, ex)
408
+ _LOGGER.error("Error general al crear moon_%s_data.json: %s", town_id, ex)
232
409
 
233
410
  async def async_step_user(
234
411
  self, user_input: dict[str, Any] | None = None
@@ -366,9 +543,10 @@ class MeteocatConfigFlow(ConfigFlow, domain=DOMAIN):
366
543
  self.province_name = station_metadata.get("provincia", {}).get("nom", "")
367
544
  self.station_status = station_metadata.get("estats", [{}])[0].get("codi", "")
368
545
 
369
- # Crear archivos de alertas y sun
546
+ # Crear archivos de alertas, sol y luna
370
547
  await self.create_alerts_file()
371
548
  await self.create_sun_file()
549
+ await self.create_moon_file()
372
550
  return await self.async_step_set_api_limits()
373
551
  except Exception as ex:
374
552
  _LOGGER.error("Error al obtener los metadatos de la estación: %s", ex)
@@ -42,20 +42,29 @@ QUOTA_BASIC = "quota_basic"
42
42
  QUOTA_XEMA = "quota_xema"
43
43
  QUOTA_QUERIES = "quota_queries"
44
44
  LIGHTNING_FILE_STATUS = "lightning_file_status"
45
+ SUN = "sun"
45
46
  SUNRISE = "sunrise"
46
47
  SUNSET = "sunset"
47
48
  SUN_FILE_STATUS = "sun_file_status"
49
+ MOON_PHASE = "moon_phase"
50
+ MOON_FILE_STATUS = "moon_file_status"
51
+ MOONRISE = "moonrise"
52
+ MOONSET = "moonset"
48
53
 
49
54
  from homeassistant.const import Platform
50
55
 
51
- ATTRIBUTION = "Powered by Meteocatpy"
56
+ ATTRIBUTION = "Powered by Meteocatpy & Solarmoonpy"
52
57
  PLATFORMS = [Platform.SENSOR, Platform.WEATHER]
53
58
  DEFAULT_NAME = "METEOCAT"
54
59
 
55
60
  # Tiempos para validación de API
56
61
  DEFAULT_VALIDITY_DAYS = 1 # Número de días a partir de los cuales se considera que el archivo de información está obsoleto
57
- DEFAULT_VALIDITY_HOURS = 5 # Hora a partir de la cual la API tiene la información actualizada de predicciones disponible para descarga
62
+ DEFAULT_VALIDITY_HOURS = 6 # Hora a partir de la cual la API tiene la información actualizada de predicciones disponible para descarga
58
63
  DEFAULT_VALIDITY_MINUTES = 0 # Minutos a partir de los cuales la API tiene la información actualizada de predicciones disponible para descarga
64
+ DEFAULT_UVI_LOW_VALIDITY_HOURS = 5 # Hora a partir de la cual la API tiene la información actualizada de datos UVI disponible para descarga con límite bajo de cuota
65
+ DEFAULT_UVI_LOW_VALIDITY_MINUTES = 0 # Minutos a partir de los cuales la API tiene la información actualizada de datos UVI disponible para descarga con límite bajo de cuota
66
+ DEFAULT_UVI_HIGH_VALIDITY_HOURS = 9 # Hora a partir de la cual la API tiene la información actualizada de datos UVI disponible para descarga con límite alto de cuota
67
+ DEFAULT_UVI_HIGH_VALIDITY_MINUTES = 0 # Minutos a partir de los cuales la API tiene la información actualizada de datos UVI disponible para descarga con límite alto de cuota
59
68
  DEFAULT_ALERT_VALIDITY_TIME = 120 # Minutos a partir de los cuales las alertas están obsoletas y se se debe proceder a una nueva llamada a la API
60
69
  DEFAULT_QUOTES_VALIDITY_TIME = 240 # Minutos a partir de los cuales los datos de cuotas están obsoletos y se se debe proceder a una nueva llamada a la API
61
70
  DEFAULT_LIGHTNING_VALIDITY_TIME = 240 # Minutos a partir de los cuales los datos de rayos están obsoletos y se se debe proceder a una nueva llamada a la API
@@ -68,6 +77,9 @@ ALERT_VALIDITY_MULTIPLIER_200 = 6 # para 100 < limit_prediccio <= 200
68
77
  ALERT_VALIDITY_MULTIPLIER_500 = 3 # para 200 < limit_prediccio <= 500
69
78
  ALERT_VALIDITY_MULTIPLIER_DEFAULT = 1 # para limit_prediccio > 500
70
79
 
80
+ # CUOTA ALTA PARA FAVORECER ACTUALIZACIONES DIARIAS DE LAS PREDICCIONES
81
+ PREDICCIO_HIGH_QUOTA_LIMIT = 550
82
+
71
83
  # Códigos de sensores de la API
72
84
  WIND_SPEED = "wind_speed" # Velocidad del viento
73
85
  WIND_DIRECTION = "wind_direction" # Dirección del viento