meteocat 0.1.41 → 0.1.42
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 +9 -0
- package/custom_components/meteocat/__init__.py +1 -1
- package/custom_components/meteocat/coordinator.py +127 -100
- package/custom_components/meteocat/manifest.json +2 -2
- package/custom_components/meteocat/version.py +1 -1
- package/package.json +1 -1
- package/pyproject.toml +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
## [0.1.42](https://github.com/figorr/meteocat/compare/v0.1.41...v0.1.42) (2024-12-28)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* 0.1.42 ([f180cf1](https://github.com/figorr/meteocat/commit/f180cf1400e614684cfee81849369bb74796ee5e))
|
|
7
|
+
* bump meteocatpy to 0.0.16 ([0e14f79](https://github.com/figorr/meteocat/commit/0e14f79445ee4c059d47a315bcbdc20858a0c666))
|
|
8
|
+
* set logger to warning when using cache data ([b840d72](https://github.com/figorr/meteocat/commit/b840d7202c439f83b08597b9365c007e92aca1c5))
|
|
9
|
+
|
|
1
10
|
## [0.1.41](https://github.com/figorr/meteocat/compare/v0.1.40...v0.1.41) (2024-12-27)
|
|
2
11
|
|
|
3
12
|
|
|
@@ -25,7 +25,7 @@ from .const import DOMAIN, PLATFORMS
|
|
|
25
25
|
_LOGGER = logging.getLogger(__name__)
|
|
26
26
|
|
|
27
27
|
# Versión
|
|
28
|
-
__version__ = "0.1.
|
|
28
|
+
__version__ = "0.1.42"
|
|
29
29
|
|
|
30
30
|
def safe_remove(path: Path, is_folder: bool = False):
|
|
31
31
|
"""Elimina de forma segura un archivo o carpeta si existe."""
|
|
@@ -84,7 +84,6 @@ class MeteocatSensorCoordinator(DataUpdateCoordinator):
|
|
|
84
84
|
self,
|
|
85
85
|
hass: HomeAssistant,
|
|
86
86
|
entry_data: dict,
|
|
87
|
-
update_interval: timedelta = DEFAULT_SENSOR_UPDATE_INTERVAL,
|
|
88
87
|
):
|
|
89
88
|
"""
|
|
90
89
|
Inicializa el coordinador de sensores de Meteocat.
|
|
@@ -103,11 +102,19 @@ class MeteocatSensorCoordinator(DataUpdateCoordinator):
|
|
|
103
102
|
self.variable_id = entry_data["variable_id"] # Usamos el ID de la variable
|
|
104
103
|
self.meteocat_station_data = MeteocatStationData(self.api_key)
|
|
105
104
|
|
|
105
|
+
self.station_file = os.path.join(
|
|
106
|
+
hass.config.path(),
|
|
107
|
+
"custom_components",
|
|
108
|
+
"meteocat",
|
|
109
|
+
"files",
|
|
110
|
+
f"station_{self.station_id.lower()}_data.json"
|
|
111
|
+
)
|
|
112
|
+
|
|
106
113
|
super().__init__(
|
|
107
114
|
hass,
|
|
108
115
|
_LOGGER,
|
|
109
116
|
name=f"{DOMAIN} Sensor Coordinator",
|
|
110
|
-
update_interval=
|
|
117
|
+
update_interval=DEFAULT_SENSOR_UPDATE_INTERVAL,
|
|
111
118
|
)
|
|
112
119
|
|
|
113
120
|
async def _async_update_data(self) -> Dict:
|
|
@@ -129,17 +136,8 @@ class MeteocatSensorCoordinator(DataUpdateCoordinator):
|
|
|
129
136
|
)
|
|
130
137
|
raise ValueError("Formato de datos inválido")
|
|
131
138
|
|
|
132
|
-
# Determinar la ruta al archivo en la carpeta raíz del repositorio
|
|
133
|
-
output_file = os.path.join(
|
|
134
|
-
self.hass.config.path(),
|
|
135
|
-
"custom_components",
|
|
136
|
-
"meteocat",
|
|
137
|
-
"files",
|
|
138
|
-
f"station_{self.station_id.lower()}_data.json"
|
|
139
|
-
)
|
|
140
|
-
|
|
141
139
|
# Guardar los datos en un archivo JSON
|
|
142
|
-
await save_json_to_file(data,
|
|
140
|
+
await save_json_to_file(data, self.station_file)
|
|
143
141
|
|
|
144
142
|
return data
|
|
145
143
|
except asyncio.TimeoutError as err:
|
|
@@ -182,13 +180,14 @@ class MeteocatSensorCoordinator(DataUpdateCoordinator):
|
|
|
182
180
|
self.station_id,
|
|
183
181
|
err,
|
|
184
182
|
)
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
183
|
+
# Intentar cargar datos en caché si hay un error
|
|
184
|
+
cached_data = load_json_from_file(self.station_file)
|
|
185
|
+
if cached_data:
|
|
186
|
+
_LOGGER.warning("Usando datos en caché para la estación %s.", self.station_id)
|
|
187
|
+
return cached_data
|
|
188
|
+
# No se puede actualizar el estado, retornar None
|
|
189
|
+
_LOGGER.error("No se pudo obtener datos actualizados ni cargar datos en caché.")
|
|
190
|
+
return None # o cualquier otro valor que indique un estado de error
|
|
192
191
|
|
|
193
192
|
class MeteocatStaticSensorCoordinator(DataUpdateCoordinator):
|
|
194
193
|
"""Coordinator to manage and update static sensor data."""
|
|
@@ -197,7 +196,6 @@ class MeteocatStaticSensorCoordinator(DataUpdateCoordinator):
|
|
|
197
196
|
self,
|
|
198
197
|
hass: HomeAssistant,
|
|
199
198
|
entry_data: dict,
|
|
200
|
-
update_interval: timedelta = DEFAULT_STATIC_SENSOR_UPDATE_INTERVAL,
|
|
201
199
|
):
|
|
202
200
|
"""
|
|
203
201
|
Initialize the MeteocatStaticSensorCoordinator.
|
|
@@ -216,7 +214,7 @@ class MeteocatStaticSensorCoordinator(DataUpdateCoordinator):
|
|
|
216
214
|
hass,
|
|
217
215
|
_LOGGER,
|
|
218
216
|
name=f"{DOMAIN} Static Sensor Coordinator",
|
|
219
|
-
update_interval=
|
|
217
|
+
update_interval=DEFAULT_STATIC_SENSOR_UPDATE_INTERVAL,
|
|
220
218
|
)
|
|
221
219
|
|
|
222
220
|
async def _async_update_data(self):
|
|
@@ -240,16 +238,15 @@ class MeteocatStaticSensorCoordinator(DataUpdateCoordinator):
|
|
|
240
238
|
}
|
|
241
239
|
|
|
242
240
|
class MeteocatUviCoordinator(DataUpdateCoordinator):
|
|
243
|
-
"""Coordinator para manejar la actualización de datos de
|
|
241
|
+
"""Coordinator para manejar la actualización de datos de UVI desde la API de Meteocat."""
|
|
244
242
|
|
|
245
243
|
def __init__(
|
|
246
244
|
self,
|
|
247
245
|
hass: HomeAssistant,
|
|
248
246
|
entry_data: dict,
|
|
249
|
-
update_interval: timedelta = DEFAULT_UVI_UPDATE_INTERVAL,
|
|
250
247
|
):
|
|
251
248
|
"""
|
|
252
|
-
Inicializa el coordinador del
|
|
249
|
+
Inicializa el coordinador del Índice UV de Meteocat.
|
|
253
250
|
|
|
254
251
|
Args:
|
|
255
252
|
hass (HomeAssistant): Instancia de Home Assistant.
|
|
@@ -259,7 +256,7 @@ class MeteocatUviCoordinator(DataUpdateCoordinator):
|
|
|
259
256
|
self.api_key = entry_data["api_key"] # Usamos la API key de la configuración
|
|
260
257
|
self.town_id = entry_data["town_id"] # Usamos el ID del municipio
|
|
261
258
|
self.meteocat_uvi_data = MeteocatUviData(self.api_key)
|
|
262
|
-
self.
|
|
259
|
+
self.uvi_file = os.path.join(
|
|
263
260
|
hass.config.path(),
|
|
264
261
|
"custom_components",
|
|
265
262
|
"meteocat",
|
|
@@ -271,16 +268,16 @@ class MeteocatUviCoordinator(DataUpdateCoordinator):
|
|
|
271
268
|
hass,
|
|
272
269
|
_LOGGER,
|
|
273
270
|
name=f"{DOMAIN} Uvi Coordinator",
|
|
274
|
-
update_interval=
|
|
271
|
+
update_interval=DEFAULT_UVI_UPDATE_INTERVAL,
|
|
275
272
|
)
|
|
276
273
|
|
|
277
274
|
async def is_uvi_data_valid(self) -> dict:
|
|
278
275
|
"""Comprueba si el archivo JSON contiene datos válidos para el día actual y devuelve los datos si son válidos."""
|
|
279
276
|
try:
|
|
280
|
-
if not os.path.exists(self.
|
|
277
|
+
if not os.path.exists(self.uvi_file):
|
|
281
278
|
return None
|
|
282
279
|
|
|
283
|
-
async with aiofiles.open(self.
|
|
280
|
+
async with aiofiles.open(self.uvi_file, "r", encoding="utf-8") as file:
|
|
284
281
|
content = await file.read()
|
|
285
282
|
data = json.loads(content)
|
|
286
283
|
|
|
@@ -294,16 +291,31 @@ class MeteocatUviCoordinator(DataUpdateCoordinator):
|
|
|
294
291
|
|
|
295
292
|
# Validar la fecha del primer elemento superior a 1 día
|
|
296
293
|
first_date = datetime.strptime(uvi_data[0].get("date"), "%Y-%m-%d").date()
|
|
297
|
-
|
|
298
|
-
return None
|
|
294
|
+
today = datetime.now(timezone.utc).date()
|
|
299
295
|
|
|
296
|
+
# Log detallado
|
|
297
|
+
_LOGGER.info(
|
|
298
|
+
"Validando datos UVI en %s: Fecha de hoy: %s, Fecha del primer elemento: %s",
|
|
299
|
+
self.uvi_file,
|
|
300
|
+
today,
|
|
301
|
+
first_date,
|
|
302
|
+
)
|
|
303
|
+
|
|
304
|
+
# Verificar si la antigüedad es mayor a un día
|
|
305
|
+
if (today - first_date).days > 1:
|
|
306
|
+
_LOGGER.info(
|
|
307
|
+
"Los datos en %s son antiguos. Se procederá a llamar a la API.",
|
|
308
|
+
self.uvi_file,
|
|
309
|
+
)
|
|
310
|
+
return None
|
|
311
|
+
_LOGGER.info("Los datos en %s son válidos. Se usarán sin llamar a la API.", self.uvi_file)
|
|
300
312
|
return data
|
|
301
313
|
except Exception as e:
|
|
302
314
|
_LOGGER.error("Error al validar el archivo JSON del índice UV: %s", e)
|
|
303
315
|
return None
|
|
304
316
|
|
|
305
317
|
async def _async_update_data(self) -> Dict:
|
|
306
|
-
"""Actualiza los datos de
|
|
318
|
+
"""Actualiza los datos de UVI desde la API de Meteocat."""
|
|
307
319
|
try:
|
|
308
320
|
# Validar el archivo JSON existente
|
|
309
321
|
valid_data = await self.is_uvi_data_valid()
|
|
@@ -316,7 +328,7 @@ class MeteocatUviCoordinator(DataUpdateCoordinator):
|
|
|
316
328
|
self.meteocat_uvi_data.get_uvi_index(self.town_id),
|
|
317
329
|
timeout=30 # Tiempo límite de 30 segundos
|
|
318
330
|
)
|
|
319
|
-
_LOGGER.debug("Datos
|
|
331
|
+
_LOGGER.debug("Datos actualizados exitosamente: %s", data)
|
|
320
332
|
|
|
321
333
|
# Validar que los datos sean un dict con una clave 'uvi'
|
|
322
334
|
if not isinstance(data, dict) or 'uvi' not in data:
|
|
@@ -324,7 +336,7 @@ class MeteocatUviCoordinator(DataUpdateCoordinator):
|
|
|
324
336
|
raise ValueError("Formato de datos inválido")
|
|
325
337
|
|
|
326
338
|
# Guardar los datos en un archivo JSON
|
|
327
|
-
await save_json_to_file(data, self.
|
|
339
|
+
await save_json_to_file(data, self.uvi_file)
|
|
328
340
|
|
|
329
341
|
return data['uvi']
|
|
330
342
|
except asyncio.TimeoutError as err:
|
|
@@ -357,12 +369,14 @@ class MeteocatUviCoordinator(DataUpdateCoordinator):
|
|
|
357
369
|
self.town_id,
|
|
358
370
|
err,
|
|
359
371
|
)
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
372
|
+
# Intentar cargar datos en caché si hay un error
|
|
373
|
+
cached_data = load_json_from_file(self.uvi_file)
|
|
374
|
+
if cached_data:
|
|
375
|
+
_LOGGER.warning("Usando datos en caché para la ciudad %s.", self.town_id)
|
|
376
|
+
return cached_data.get('uvi', [])
|
|
377
|
+
# No se puede actualizar el estado, retornar None
|
|
378
|
+
_LOGGER.error("No se pudo obtener datos actualizados ni cargar datos en caché.")
|
|
379
|
+
return None
|
|
366
380
|
|
|
367
381
|
class MeteocatUviFileCoordinator(DataUpdateCoordinator):
|
|
368
382
|
"""Coordinator to read and process UV data from a file."""
|
|
@@ -371,7 +385,6 @@ class MeteocatUviFileCoordinator(DataUpdateCoordinator):
|
|
|
371
385
|
self,
|
|
372
386
|
hass: HomeAssistant,
|
|
373
387
|
entry_data: dict,
|
|
374
|
-
update_interval: timedelta = DEFAULT_UVI_SENSOR_UPDATE_INTERVAL,
|
|
375
388
|
):
|
|
376
389
|
"""
|
|
377
390
|
Inicializa el coordinador del sensor del Índice UV de Meteocat.
|
|
@@ -387,7 +400,7 @@ class MeteocatUviFileCoordinator(DataUpdateCoordinator):
|
|
|
387
400
|
hass,
|
|
388
401
|
_LOGGER,
|
|
389
402
|
name=f"{DOMAIN} Uvi File Coordinator",
|
|
390
|
-
update_interval=
|
|
403
|
+
update_interval=DEFAULT_UVI_SENSOR_UPDATE_INTERVAL,
|
|
391
404
|
)
|
|
392
405
|
self._file_path = os.path.join(
|
|
393
406
|
hass.config.path("custom_components/meteocat/files"),
|
|
@@ -449,7 +462,6 @@ class MeteocatEntityCoordinator(DataUpdateCoordinator):
|
|
|
449
462
|
self,
|
|
450
463
|
hass: HomeAssistant,
|
|
451
464
|
entry_data: dict,
|
|
452
|
-
update_interval: timedelta = DEFAULT_ENTITY_UPDATE_INTERVAL,
|
|
453
465
|
):
|
|
454
466
|
"""
|
|
455
467
|
Inicializa el coordinador de datos para entidades de predicción.
|
|
@@ -468,35 +480,64 @@ class MeteocatEntityCoordinator(DataUpdateCoordinator):
|
|
|
468
480
|
self.variable_id = entry_data["variable_id"]
|
|
469
481
|
self.meteocat_forecast = MeteocatForecast(self.api_key)
|
|
470
482
|
|
|
483
|
+
self.hourly_file = os.path.join(
|
|
484
|
+
hass.config.path(),
|
|
485
|
+
"custom_components",
|
|
486
|
+
"meteocat",
|
|
487
|
+
"files",
|
|
488
|
+
f"forecast_{self.town_id}_hourly_data.json",
|
|
489
|
+
)
|
|
490
|
+
self.daily_file = os.path.join(
|
|
491
|
+
hass.config.path(),
|
|
492
|
+
"custom_components",
|
|
493
|
+
"meteocat",
|
|
494
|
+
"files",
|
|
495
|
+
f"forecast_{self.town_id}_daily_data.json",
|
|
496
|
+
)
|
|
497
|
+
|
|
471
498
|
super().__init__(
|
|
472
499
|
hass,
|
|
473
500
|
_LOGGER,
|
|
474
501
|
name=f"{DOMAIN} Entity Coordinator",
|
|
475
|
-
update_interval=
|
|
502
|
+
update_interval=DEFAULT_ENTITY_UPDATE_INTERVAL,
|
|
476
503
|
)
|
|
477
504
|
|
|
478
|
-
async def
|
|
479
|
-
"""
|
|
505
|
+
async def validate_forecast_data(self, file_path: str) -> dict:
|
|
506
|
+
"""Valida y retorna datos de predicción si son válidos."""
|
|
480
507
|
if not os.path.exists(file_path):
|
|
481
|
-
|
|
482
|
-
|
|
508
|
+
_LOGGER.info("El archivo %s no existe. Se considerará inválido.", file_path)
|
|
509
|
+
return None
|
|
483
510
|
try:
|
|
484
511
|
async with aiofiles.open(file_path, "r", encoding="utf-8") as f:
|
|
485
512
|
content = await f.read()
|
|
486
513
|
data = json.loads(content)
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
return
|
|
490
|
-
|
|
514
|
+
if "dies" not in data or not data["dies"]:
|
|
515
|
+
_LOGGER.warning("El archivo %s no contiene datos válidos.", file_path)
|
|
516
|
+
return None
|
|
491
517
|
# Obtener la fecha del primer día
|
|
492
518
|
first_date = datetime.fromisoformat(data["dies"][0]["data"].rstrip("Z")).date()
|
|
493
519
|
today = datetime.now(timezone.utc).date()
|
|
494
520
|
|
|
521
|
+
# Log detallado
|
|
522
|
+
_LOGGER.info(
|
|
523
|
+
"Validando datos en %s: Fecha de hoy: %s, Fecha del primer elemento: %s",
|
|
524
|
+
file_path,
|
|
525
|
+
today,
|
|
526
|
+
first_date,
|
|
527
|
+
)
|
|
528
|
+
|
|
495
529
|
# Verificar si la antigüedad es mayor a un día
|
|
496
|
-
|
|
530
|
+
if (today - first_date).days > 1:
|
|
531
|
+
_LOGGER.info(
|
|
532
|
+
"Los datos en %s son antiguos. Se procederá a llamar a la API.",
|
|
533
|
+
file_path,
|
|
534
|
+
)
|
|
535
|
+
return None
|
|
536
|
+
_LOGGER.info("Los datos en %s son válidos. Se usarán sin llamar a la API.", file_path)
|
|
537
|
+
return data
|
|
497
538
|
except Exception as e:
|
|
498
539
|
_LOGGER.warning("Error validando datos en %s: %s", file_path, e)
|
|
499
|
-
return
|
|
540
|
+
return None
|
|
500
541
|
|
|
501
542
|
async def _fetch_and_save_data(self, api_method, file_path: str) -> dict:
|
|
502
543
|
"""Obtiene datos de la API y los guarda en un archivo JSON."""
|
|
@@ -504,44 +545,25 @@ class MeteocatEntityCoordinator(DataUpdateCoordinator):
|
|
|
504
545
|
await save_json_to_file(data, file_path)
|
|
505
546
|
return data
|
|
506
547
|
|
|
507
|
-
async def _async_update_data(self) ->
|
|
508
|
-
"""Actualiza los datos de predicción
|
|
509
|
-
hourly_file = os.path.join(
|
|
510
|
-
self.hass.config.path(),
|
|
511
|
-
"custom_components",
|
|
512
|
-
"meteocat",
|
|
513
|
-
"files",
|
|
514
|
-
f"forecast_{self.town_id.lower()}_hourly_data.json",
|
|
515
|
-
)
|
|
516
|
-
daily_file = os.path.join(
|
|
517
|
-
self.hass.config.path(),
|
|
518
|
-
"custom_components",
|
|
519
|
-
"meteocat",
|
|
520
|
-
"files",
|
|
521
|
-
f"forecast_{self.town_id.lower()}_daily_data.json",
|
|
522
|
-
)
|
|
523
|
-
|
|
548
|
+
async def _async_update_data(self) -> dict:
|
|
549
|
+
"""Actualiza los datos de predicción horaria y diaria."""
|
|
524
550
|
try:
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
self.meteocat_forecast.get_prediccion_horaria, hourly_file
|
|
551
|
+
# Validar o actualizar datos horarios
|
|
552
|
+
hourly_data = await self.validate_forecast_data(self.hourly_file)
|
|
553
|
+
if not hourly_data:
|
|
554
|
+
hourly_data = await self._fetch_and_save_data(
|
|
555
|
+
self.meteocat_forecast.get_prediccion_horaria, self.hourly_file
|
|
530
556
|
)
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
self.meteocat_forecast.get_prediccion_diaria, daily_file
|
|
557
|
+
|
|
558
|
+
# Validar o actualizar datos diarios
|
|
559
|
+
daily_data = await self.validate_forecast_data(self.daily_file)
|
|
560
|
+
if not daily_data:
|
|
561
|
+
daily_data = await self._fetch_and_save_data(
|
|
562
|
+
self.meteocat_forecast.get_prediccion_diaria, self.daily_file
|
|
537
563
|
)
|
|
538
|
-
)
|
|
539
564
|
|
|
540
|
-
_LOGGER.debug(
|
|
541
|
-
"Datos de predicción horaria y diaria actualizados correctamente para %s.",
|
|
542
|
-
self.town_id,
|
|
543
|
-
)
|
|
544
565
|
return {"hourly": hourly_data, "daily": daily_data}
|
|
566
|
+
|
|
545
567
|
except asyncio.TimeoutError as err:
|
|
546
568
|
_LOGGER.warning("Tiempo de espera agotado al obtener datos de predicción.")
|
|
547
569
|
raise ConfigEntryNotReady from err
|
|
@@ -568,10 +590,19 @@ class MeteocatEntityCoordinator(DataUpdateCoordinator):
|
|
|
568
590
|
raise
|
|
569
591
|
except Exception as err:
|
|
570
592
|
_LOGGER.exception("Error inesperado al obtener datos de predicción: %s", err)
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
593
|
+
|
|
594
|
+
# Si ocurre un error, intentar cargar datos desde los archivos locales
|
|
595
|
+
hourly_cache = load_json_from_file(self.hourly_file) or {}
|
|
596
|
+
daily_cache = load_json_from_file(self.daily_file) or {}
|
|
597
|
+
|
|
598
|
+
_LOGGER.warning(
|
|
599
|
+
"Cargando datos desde caché para %s. Datos horarios: %s, Datos diarios: %s",
|
|
600
|
+
self.town_id,
|
|
601
|
+
"Encontrados" if hourly_cache else "No encontrados",
|
|
602
|
+
"Encontrados" if daily_cache else "No encontrados",
|
|
603
|
+
)
|
|
604
|
+
|
|
605
|
+
return {"hourly": hourly_cache, "daily": daily_cache}
|
|
575
606
|
|
|
576
607
|
def get_condition_from_code(code: int) -> str:
|
|
577
608
|
"""Devuelve la condición meteorológica basada en el código."""
|
|
@@ -584,7 +615,6 @@ class HourlyForecastCoordinator(DataUpdateCoordinator):
|
|
|
584
615
|
self,
|
|
585
616
|
hass: HomeAssistant,
|
|
586
617
|
entry_data: dict,
|
|
587
|
-
update_interval: timedelta = DEFAULT_HOURLY_FORECAST_UPDATE_INTERVAL,
|
|
588
618
|
):
|
|
589
619
|
"""Inicializa el coordinador para predicciones horarias."""
|
|
590
620
|
self.town_name = entry_data["town_name"]
|
|
@@ -602,7 +632,7 @@ class HourlyForecastCoordinator(DataUpdateCoordinator):
|
|
|
602
632
|
hass,
|
|
603
633
|
_LOGGER,
|
|
604
634
|
name=f"{DOMAIN} Hourly Forecast Coordinator",
|
|
605
|
-
update_interval=
|
|
635
|
+
update_interval=DEFAULT_HOURLY_FORECAST_UPDATE_INTERVAL,
|
|
606
636
|
)
|
|
607
637
|
|
|
608
638
|
async def _is_data_valid(self) -> bool:
|
|
@@ -716,7 +746,6 @@ class DailyForecastCoordinator(DataUpdateCoordinator):
|
|
|
716
746
|
self,
|
|
717
747
|
hass: HomeAssistant,
|
|
718
748
|
entry_data: dict,
|
|
719
|
-
update_interval: timedelta = DEFAULT_DAILY_FORECAST_UPDATE_INTERVAL,
|
|
720
749
|
):
|
|
721
750
|
"""Inicializa el coordinador para predicciones diarias."""
|
|
722
751
|
self.town_name = entry_data["town_name"]
|
|
@@ -734,7 +763,7 @@ class DailyForecastCoordinator(DataUpdateCoordinator):
|
|
|
734
763
|
hass,
|
|
735
764
|
_LOGGER,
|
|
736
765
|
name=f"{DOMAIN} Daily Forecast Coordinator",
|
|
737
|
-
update_interval=
|
|
766
|
+
update_interval=DEFAULT_DAILY_FORECAST_UPDATE_INTERVAL,
|
|
738
767
|
)
|
|
739
768
|
|
|
740
769
|
async def _is_data_valid(self) -> bool:
|
|
@@ -827,7 +856,6 @@ class MeteocatConditionCoordinator(DataUpdateCoordinator):
|
|
|
827
856
|
self,
|
|
828
857
|
hass: HomeAssistant,
|
|
829
858
|
entry_data: dict,
|
|
830
|
-
update_interval: timedelta = DEFAULT_CONDITION_SENSOR_UPDATE_INTERVAL,
|
|
831
859
|
):
|
|
832
860
|
"""
|
|
833
861
|
Initialize the Meteocat Condition Coordinator.
|
|
@@ -844,7 +872,7 @@ class MeteocatConditionCoordinator(DataUpdateCoordinator):
|
|
|
844
872
|
hass,
|
|
845
873
|
_LOGGER,
|
|
846
874
|
name=f"{DOMAIN} Condition Coordinator",
|
|
847
|
-
update_interval=
|
|
875
|
+
update_interval=DEFAULT_CONDITION_SENSOR_UPDATE_INTERVAL,
|
|
848
876
|
)
|
|
849
877
|
|
|
850
878
|
self._file_path = os.path.join(
|
|
@@ -927,7 +955,6 @@ class MeteocatTempForecastCoordinator(DataUpdateCoordinator):
|
|
|
927
955
|
self,
|
|
928
956
|
hass: HomeAssistant,
|
|
929
957
|
entry_data: dict,
|
|
930
|
-
update_interval: timedelta = DEFAULT_TEMP_FORECAST_UPDATE_INTERVAL,
|
|
931
958
|
):
|
|
932
959
|
"""Inicializa el coordinador para predicciones diarias."""
|
|
933
960
|
self.town_name = entry_data["town_name"]
|
|
@@ -945,7 +972,7 @@ class MeteocatTempForecastCoordinator(DataUpdateCoordinator):
|
|
|
945
972
|
hass,
|
|
946
973
|
_LOGGER,
|
|
947
974
|
name=f"{DOMAIN} Daily Forecast Coordinator",
|
|
948
|
-
update_interval=
|
|
975
|
+
update_interval=DEFAULT_TEMP_FORECAST_UPDATE_INTERVAL,
|
|
949
976
|
)
|
|
950
977
|
|
|
951
978
|
async def _is_data_valid(self) -> bool:
|
|
@@ -990,7 +1017,7 @@ class MeteocatTempForecastCoordinator(DataUpdateCoordinator):
|
|
|
990
1017
|
# Usar datos del día actual si están disponibles
|
|
991
1018
|
today_temp_forecast = self.get_temp_forecast_for_today(data)
|
|
992
1019
|
if today_temp_forecast:
|
|
993
|
-
parsed_data = self.
|
|
1020
|
+
parsed_data = self.parse_temp_forecast(today_temp_forecast)
|
|
994
1021
|
return parsed_data
|
|
995
1022
|
except Exception as e:
|
|
996
1023
|
_LOGGER.warning("Error leyendo archivo de predicción diaria: %s", e)
|
|
@@ -1009,7 +1036,7 @@ class MeteocatTempForecastCoordinator(DataUpdateCoordinator):
|
|
|
1009
1036
|
return dia
|
|
1010
1037
|
return None
|
|
1011
1038
|
|
|
1012
|
-
def
|
|
1039
|
+
def parse_temp_forecast(self, dia: dict) -> dict:
|
|
1013
1040
|
"""Convierte un día de predicción en un diccionario con los datos necesarios."""
|
|
1014
1041
|
variables = dia.get("variables", {})
|
|
1015
1042
|
|
|
@@ -7,6 +7,6 @@
|
|
|
7
7
|
"iot_class": "cloud_polling",
|
|
8
8
|
"documentation": "https://gitlab.com/figorr/meteocat",
|
|
9
9
|
"loggers": ["meteocatpy"],
|
|
10
|
-
"requirements": ["meteocatpy==0.0.
|
|
11
|
-
"version": "0.1.
|
|
10
|
+
"requirements": ["meteocatpy==0.0.16", "packaging>=20.3", "wrapt>=1.14.0"],
|
|
11
|
+
"version": "0.1.42"
|
|
12
12
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
# version.py
|
|
2
|
-
__version__ = "0.1.
|
|
2
|
+
__version__ = "0.1.42"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "meteocat",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.42",
|
|
4
4
|
"description": "[](https://opensource.org/licenses/Apache-2.0)\r [](https://pypi.org/project/meteocat)\r [](https://gitlab.com/figorr/meteocat/commits/master)",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"directories": {
|