meteocat 2.1.0 → 2.2.3
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 +18 -0
- package/README.md +1 -1
- package/custom_components/meteocat/__init__.py +29 -1
- package/custom_components/meteocat/config_flow.py +140 -1
- package/custom_components/meteocat/const.py +14 -0
- package/custom_components/meteocat/coordinator.py +524 -9
- package/custom_components/meteocat/manifest.json +2 -2
- package/custom_components/meteocat/options_flow.py +30 -4
- package/custom_components/meteocat/sensor.py +420 -4
- package/custom_components/meteocat/strings.json +197 -4
- package/custom_components/meteocat/translations/ca.json +197 -4
- package/custom_components/meteocat/translations/en.json +197 -4
- package/custom_components/meteocat/translations/es.json +197 -4
- package/custom_components/meteocat/version.py +1 -1
- package/images/api_limits.png +0 -0
- package/images/diagnostic_sensors.png +0 -0
- package/images/dynamic_sensors.png +0 -0
- package/package.json +1 -1
- package/poetry.lock +598 -586
- package/pyproject.toml +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,21 @@
|
|
|
1
|
+
## [2.2.3](https://github.com/figorr/meteocat/compare/v2.2.2...v2.2.3) (2025-02-08)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* 2.2.3 ([ce224a0](https://github.com/figorr/meteocat/commit/ce224a097e7c879c46985ff3a16143de1b822006))
|
|
7
|
+
* bump meteocatpy to 1.0.1 ([7119065](https://github.com/figorr/meteocat/commit/711906534fca5c61a9a3ab968a3572e70f05929e))
|
|
8
|
+
* new lightning sensors ([8528f57](https://github.com/figorr/meteocat/commit/8528f57d688f7fc21f66715ffeac086895afd1aa))
|
|
9
|
+
* update README ([10c86e5](https://github.com/figorr/meteocat/commit/10c86e5e373c661cf23524421c756374711d89fe))
|
|
10
|
+
|
|
11
|
+
## [2.2.2](https://github.com/figorr/meteocat/compare/v2.2.1...v2.2.2) (2025-02-04)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
### Bug Fixes
|
|
15
|
+
|
|
16
|
+
* 2.2.2 ([3667e5d](https://github.com/figorr/meteocat/commit/3667e5d65069ee0079ebbaebeab6c929be8b9630))
|
|
17
|
+
* fix version 2.2.1 ([359cc7f](https://github.com/figorr/meteocat/commit/359cc7f7a9f1f025890bedc5177785016e9968d1))
|
|
18
|
+
|
|
1
19
|
# [2.1.0](https://github.com/figorr/meteocat/compare/v2.0.3...v2.1.0) (2025-01-27)
|
|
2
20
|
|
|
3
21
|
|
package/README.md
CHANGED
|
@@ -56,7 +56,7 @@ Once you pick the town you will be prompted to pick a station from the list. The
|
|
|
56
56
|
|
|
57
57
|

|
|
58
58
|
|
|
59
|
-
Then you will be asked to set the
|
|
59
|
+
Then you will be asked to set the API limits from your plan.
|
|
60
60
|
|
|
61
61
|

|
|
62
62
|
|
|
@@ -22,6 +22,10 @@ from .coordinator import (
|
|
|
22
22
|
MeteocatTempForecastCoordinator,
|
|
23
23
|
MeteocatAlertsCoordinator,
|
|
24
24
|
MeteocatAlertsRegionCoordinator,
|
|
25
|
+
MeteocatQuotesCoordinator,
|
|
26
|
+
MeteocatQuotesFileCoordinator,
|
|
27
|
+
MeteocatLightningCoordinator,
|
|
28
|
+
MeteocatLightningFileCoordinator,
|
|
25
29
|
)
|
|
26
30
|
|
|
27
31
|
from .const import DOMAIN, PLATFORMS
|
|
@@ -29,7 +33,7 @@ from .const import DOMAIN, PLATFORMS
|
|
|
29
33
|
_LOGGER = logging.getLogger(__name__)
|
|
30
34
|
|
|
31
35
|
# Versión
|
|
32
|
-
__version__ = "2.
|
|
36
|
+
__version__ = "2.2.3"
|
|
33
37
|
|
|
34
38
|
# Definir el esquema de configuración CONFIG_SCHEMA
|
|
35
39
|
CONFIG_SCHEMA = vol.Schema(
|
|
@@ -129,6 +133,18 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|
|
129
133
|
alerts_region_coordinator = MeteocatAlertsRegionCoordinator(hass=hass, entry_data=entry_data)
|
|
130
134
|
await alerts_region_coordinator.async_config_entry_first_refresh()
|
|
131
135
|
|
|
136
|
+
quotes_coordinator = MeteocatQuotesCoordinator(hass=hass, entry_data=entry_data)
|
|
137
|
+
await quotes_coordinator.async_config_entry_first_refresh()
|
|
138
|
+
|
|
139
|
+
quotes_file_coordinator = MeteocatQuotesFileCoordinator(hass=hass, entry_data=entry_data)
|
|
140
|
+
await quotes_file_coordinator.async_config_entry_first_refresh()
|
|
141
|
+
|
|
142
|
+
lightning_coordinator = MeteocatLightningCoordinator(hass=hass, entry_data=entry_data)
|
|
143
|
+
await lightning_coordinator.async_config_entry_first_refresh()
|
|
144
|
+
|
|
145
|
+
lightning_file_coordinator = MeteocatLightningFileCoordinator(hass=hass, entry_data=entry_data)
|
|
146
|
+
await lightning_file_coordinator.async_config_entry_first_refresh()
|
|
147
|
+
|
|
132
148
|
except Exception as err: # Capturar todos los errores
|
|
133
149
|
_LOGGER.exception(f"Error al inicializar los coordinadores: {err}")
|
|
134
150
|
return False
|
|
@@ -147,6 +163,10 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|
|
147
163
|
"temp_forecast_coordinator": temp_forecast_coordinator,
|
|
148
164
|
"alerts_coordinator": alerts_coordinator,
|
|
149
165
|
"alerts_region_coordinator": alerts_region_coordinator,
|
|
166
|
+
"quotes_coordinator": quotes_coordinator,
|
|
167
|
+
"quotes_file_coordinator": quotes_file_coordinator,
|
|
168
|
+
"lightning_coordinator": lightning_coordinator,
|
|
169
|
+
"lightning_file_coordinator": lightning_file_coordinator,
|
|
150
170
|
**entry_data,
|
|
151
171
|
}
|
|
152
172
|
|
|
@@ -213,6 +233,12 @@ async def async_remove_entry(hass: HomeAssistant, entry: ConfigEntry) -> None:
|
|
|
213
233
|
alerts_file = files_folder / "alerts.json"
|
|
214
234
|
alerts_region_file = files_folder / f"alerts_{region_id}.json"
|
|
215
235
|
|
|
236
|
+
# Archivo JSON de cuotas
|
|
237
|
+
quotes_file = files_folder / f"quotes.json"
|
|
238
|
+
|
|
239
|
+
# Archivo JSON de rayos
|
|
240
|
+
lightning_file = files_folder / f"lightning_{region_id}.json"
|
|
241
|
+
|
|
216
242
|
# Validar la ruta base
|
|
217
243
|
if not custom_components_path.exists():
|
|
218
244
|
_LOGGER.warning(f"La ruta {custom_components_path} no existe. No se realizará la limpieza.")
|
|
@@ -226,6 +252,8 @@ async def async_remove_entry(hass: HomeAssistant, entry: ConfigEntry) -> None:
|
|
|
226
252
|
safe_remove(forecast_hourly_data_file)
|
|
227
253
|
safe_remove(forecast_daily_data_file)
|
|
228
254
|
safe_remove(alerts_file)
|
|
255
|
+
safe_remove(quotes_file)
|
|
229
256
|
safe_remove(alerts_region_file)
|
|
257
|
+
safe_remove(lightning_file)
|
|
230
258
|
safe_remove(assets_folder, is_folder=True)
|
|
231
259
|
safe_remove(files_folder, is_folder=True)
|
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
|
+
import asyncio
|
|
4
5
|
import json
|
|
5
6
|
import logging
|
|
6
7
|
from pathlib import Path
|
|
7
8
|
from typing import Any
|
|
9
|
+
from datetime import datetime, timezone
|
|
10
|
+
from zoneinfo import ZoneInfo
|
|
8
11
|
|
|
9
12
|
import voluptuous as vol
|
|
10
13
|
from aiohttp import ClientError
|
|
11
14
|
import aiofiles
|
|
15
|
+
import unicodedata
|
|
12
16
|
|
|
13
17
|
from homeassistant.config_entries import ConfigEntry, ConfigFlow, ConfigFlowResult
|
|
14
18
|
from homeassistant.core import callback
|
|
@@ -34,7 +38,10 @@ from .const import (
|
|
|
34
38
|
PROVINCE_NAME,
|
|
35
39
|
STATION_STATUS,
|
|
36
40
|
LIMIT_XEMA,
|
|
37
|
-
LIMIT_PREDICCIO
|
|
41
|
+
LIMIT_PREDICCIO,
|
|
42
|
+
LIMIT_XDDE,
|
|
43
|
+
LIMIT_BASIC,
|
|
44
|
+
LIMIT_QUOTA
|
|
38
45
|
)
|
|
39
46
|
|
|
40
47
|
from .options_flow import MeteocatOptionsFlowHandler
|
|
@@ -43,11 +50,19 @@ from meteocatpy.symbols import MeteocatSymbols
|
|
|
43
50
|
from meteocatpy.variables import MeteocatVariables
|
|
44
51
|
from meteocatpy.townstations import MeteocatTownStations
|
|
45
52
|
from meteocatpy.infostation import MeteocatInfoStation
|
|
53
|
+
from meteocatpy.quotes import MeteocatQuotes
|
|
46
54
|
|
|
47
55
|
from meteocatpy.exceptions import BadRequestError, ForbiddenError, TooManyRequestsError, InternalServerError, UnknownAPIError
|
|
48
56
|
|
|
49
57
|
_LOGGER = logging.getLogger(__name__)
|
|
50
58
|
|
|
59
|
+
TIMEZONE = ZoneInfo("Europe/Madrid")
|
|
60
|
+
|
|
61
|
+
def normalize_name(name):
|
|
62
|
+
"""Normaliza el nombre eliminando acentos y convirtiendo a minúsculas."""
|
|
63
|
+
name = unicodedata.normalize("NFKD", name).encode("ASCII", "ignore").decode("utf-8")
|
|
64
|
+
return name.lower()
|
|
65
|
+
|
|
51
66
|
class MeteocatConfigFlow(ConfigFlow, domain=DOMAIN):
|
|
52
67
|
"""Flujo de configuración para Meteocat."""
|
|
53
68
|
|
|
@@ -60,8 +75,115 @@ class MeteocatConfigFlow(ConfigFlow, domain=DOMAIN):
|
|
|
60
75
|
self.variable_id: str | None = None
|
|
61
76
|
self.station_id: str | None = None
|
|
62
77
|
self.station_name: str | None = None
|
|
78
|
+
self.region_id: str | None = None
|
|
63
79
|
self._cache = {}
|
|
64
80
|
|
|
81
|
+
async def fetch_and_save_quotes(self, api_key):
|
|
82
|
+
"""Obtiene las cuotas de la API de Meteocat y las guarda en quotes.json."""
|
|
83
|
+
meteocat_quotes = MeteocatQuotes(api_key)
|
|
84
|
+
quotes_dir = os.path.join(
|
|
85
|
+
self.hass.config.path(),
|
|
86
|
+
"custom_components",
|
|
87
|
+
"meteocat",
|
|
88
|
+
"files"
|
|
89
|
+
)
|
|
90
|
+
os.makedirs(quotes_dir, exist_ok=True)
|
|
91
|
+
quotes_file = os.path.join(quotes_dir, "quotes.json")
|
|
92
|
+
|
|
93
|
+
try:
|
|
94
|
+
data = await asyncio.wait_for(
|
|
95
|
+
meteocat_quotes.get_quotes(),
|
|
96
|
+
timeout=30
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
# Modificar los nombres de los planes con normalización
|
|
100
|
+
plan_mapping = {
|
|
101
|
+
"xdde_": "XDDE",
|
|
102
|
+
"prediccio_": "Prediccio",
|
|
103
|
+
"referencia basic": "Basic",
|
|
104
|
+
"xema_": "XEMA",
|
|
105
|
+
"quota": "Quota"
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
modified_plans = []
|
|
109
|
+
for plan in data["plans"]:
|
|
110
|
+
normalized_nom = normalize_name(plan["nom"])
|
|
111
|
+
new_name = next((v for k, v in plan_mapping.items() if normalized_nom.startswith(k)), plan["nom"])
|
|
112
|
+
|
|
113
|
+
modified_plans.append({
|
|
114
|
+
"nom": new_name,
|
|
115
|
+
"periode": plan["periode"],
|
|
116
|
+
"maxConsultes": plan["maxConsultes"],
|
|
117
|
+
"consultesRestants": plan["consultesRestants"],
|
|
118
|
+
"consultesRealitzades": plan["consultesRealitzades"]
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
# Añadir la clave 'actualitzat' con la fecha y hora actual de la zona horaria local
|
|
122
|
+
current_time = datetime.now(timezone.utc).astimezone(TIMEZONE).isoformat()
|
|
123
|
+
data_with_timestamp = {
|
|
124
|
+
"actualitzat": {
|
|
125
|
+
"dataUpdate": current_time
|
|
126
|
+
},
|
|
127
|
+
"client": data["client"],
|
|
128
|
+
"plans": modified_plans
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
# Guardar los datos en el archivo JSON
|
|
132
|
+
async with aiofiles.open(quotes_file, "w", encoding="utf-8") as file:
|
|
133
|
+
await file.write(json.dumps(data_with_timestamp, ensure_ascii=False, indent=4))
|
|
134
|
+
|
|
135
|
+
_LOGGER.info("Cuotas guardadas exitosamente en %s", quotes_file)
|
|
136
|
+
|
|
137
|
+
except Exception as ex:
|
|
138
|
+
_LOGGER.error("Error al obtener o guardar las cuotas: %s", ex)
|
|
139
|
+
raise HomeAssistantError("No se pudieron obtener las cuotas de la API")
|
|
140
|
+
|
|
141
|
+
async def create_alerts_file(self):
|
|
142
|
+
"""Crea el archivo alerts.json si no existe."""
|
|
143
|
+
alerts_dir = os.path.join(
|
|
144
|
+
self.hass.config.path(),
|
|
145
|
+
"custom_components",
|
|
146
|
+
"meteocat",
|
|
147
|
+
"files"
|
|
148
|
+
)
|
|
149
|
+
os.makedirs(alerts_dir, exist_ok=True)
|
|
150
|
+
alerts_file = os.path.join(alerts_dir, "alerts.json")
|
|
151
|
+
|
|
152
|
+
if not os.path.exists(alerts_file):
|
|
153
|
+
initial_data = {
|
|
154
|
+
"actualitzat": {
|
|
155
|
+
"dataUpdate": "1970-01-01T00:00:00+00:00"
|
|
156
|
+
},
|
|
157
|
+
"dades": []
|
|
158
|
+
}
|
|
159
|
+
async with aiofiles.open(alerts_file, "w", encoding="utf-8") as file:
|
|
160
|
+
await file.write(json.dumps(initial_data, ensure_ascii=False, indent=4))
|
|
161
|
+
|
|
162
|
+
_LOGGER.info("Archivo alerts.json creado en %s", alerts_file)
|
|
163
|
+
|
|
164
|
+
async def create_lightning_file(self):
|
|
165
|
+
"""Crea el archivo lightning_{self.region_id}.json si no existe."""
|
|
166
|
+
lightning_dir = os.path.join(
|
|
167
|
+
self.hass.config.path(),
|
|
168
|
+
"custom_components",
|
|
169
|
+
"meteocat",
|
|
170
|
+
"files"
|
|
171
|
+
)
|
|
172
|
+
os.makedirs(lightning_dir, exist_ok=True)
|
|
173
|
+
lightning_file = os.path.join(lightning_dir, f"lightning_{self.region_id}.json")
|
|
174
|
+
|
|
175
|
+
if not os.path.exists(lightning_file):
|
|
176
|
+
initial_data = {
|
|
177
|
+
"actualitzat": {
|
|
178
|
+
"dataUpdate": "1970-01-01T00:00:00+00:00"
|
|
179
|
+
},
|
|
180
|
+
"dades": []
|
|
181
|
+
}
|
|
182
|
+
async with aiofiles.open(lightning_file, "w", encoding="utf-8") as file:
|
|
183
|
+
await file.write(json.dumps(initial_data, ensure_ascii=False, indent=4))
|
|
184
|
+
|
|
185
|
+
_LOGGER.info("Archivo %s creado", lightning_file)
|
|
186
|
+
|
|
65
187
|
async def async_step_user(
|
|
66
188
|
self, user_input: dict[str, Any] | None = None
|
|
67
189
|
) -> ConfigFlowResult:
|
|
@@ -75,6 +197,10 @@ class MeteocatConfigFlow(ConfigFlow, domain=DOMAIN):
|
|
|
75
197
|
|
|
76
198
|
try:
|
|
77
199
|
self.municipis = await town_client.get_municipis()
|
|
200
|
+
# Aquí obtenemos y guardamos las cuotas
|
|
201
|
+
await self.fetch_and_save_quotes(self.api_key)
|
|
202
|
+
# Aquí creamos el archivo alerts.json si no existe
|
|
203
|
+
await self.create_alerts_file()
|
|
78
204
|
except (BadRequestError, ForbiddenError, TooManyRequestsError, InternalServerError, UnknownAPIError) as ex:
|
|
79
205
|
_LOGGER.error("Error al conectar con la API de Meteocat: %s", ex)
|
|
80
206
|
errors["base"] = "cannot_connect"
|
|
@@ -205,6 +331,10 @@ class MeteocatConfigFlow(ConfigFlow, domain=DOMAIN):
|
|
|
205
331
|
self.province_id = station_metadata.get("provincia", {}).get("codi", "")
|
|
206
332
|
self.province_name = station_metadata.get("provincia", {}).get("nom", "")
|
|
207
333
|
self.station_status = station_metadata.get("estats", [{}])[0].get("codi", "")
|
|
334
|
+
|
|
335
|
+
# Crear el archivo lightning después de obtener region_id
|
|
336
|
+
await self.create_lightning_file()
|
|
337
|
+
|
|
208
338
|
return await self.async_step_set_api_limits()
|
|
209
339
|
except Exception as ex:
|
|
210
340
|
_LOGGER.error("Error al obtener los metadatos de la estación: %s", ex)
|
|
@@ -231,6 +361,9 @@ class MeteocatConfigFlow(ConfigFlow, domain=DOMAIN):
|
|
|
231
361
|
if user_input is not None:
|
|
232
362
|
self.limit_xema = user_input.get(LIMIT_XEMA, 750)
|
|
233
363
|
self.limit_prediccio = user_input.get(LIMIT_PREDICCIO, 100)
|
|
364
|
+
self.limit_xdde = user_input.get(LIMIT_XDDE, 250)
|
|
365
|
+
self.limit_quota = user_input.get(LIMIT_QUOTA, 300)
|
|
366
|
+
self.limit_basic = user_input.get(LIMIT_BASIC, 300)
|
|
234
367
|
return self.async_create_entry(
|
|
235
368
|
title=self.selected_municipi["nom"],
|
|
236
369
|
data={
|
|
@@ -252,6 +385,9 @@ class MeteocatConfigFlow(ConfigFlow, domain=DOMAIN):
|
|
|
252
385
|
STATION_STATUS: str(self.station_status),
|
|
253
386
|
LIMIT_XEMA: self.limit_xema,
|
|
254
387
|
LIMIT_PREDICCIO: self.limit_prediccio,
|
|
388
|
+
LIMIT_XDDE: self.limit_xdde,
|
|
389
|
+
LIMIT_QUOTA: self.limit_quota,
|
|
390
|
+
LIMIT_BASIC: self.limit_basic,
|
|
255
391
|
},
|
|
256
392
|
)
|
|
257
393
|
|
|
@@ -259,6 +395,9 @@ class MeteocatConfigFlow(ConfigFlow, domain=DOMAIN):
|
|
|
259
395
|
{
|
|
260
396
|
vol.Required(LIMIT_XEMA, default=750): cv.positive_int,
|
|
261
397
|
vol.Required(LIMIT_PREDICCIO, default=100): cv.positive_int,
|
|
398
|
+
vol.Required(LIMIT_XDDE, default=250): cv.positive_int,
|
|
399
|
+
vol.Required(LIMIT_QUOTA, default=300): cv.positive_int,
|
|
400
|
+
vol.Required(LIMIT_BASIC, default=2000): cv.positive_int,
|
|
262
401
|
}
|
|
263
402
|
)
|
|
264
403
|
|
|
@@ -18,6 +18,9 @@ PROVINCE_ID = "province_id"
|
|
|
18
18
|
PROVINCE_NAME = "province_name"
|
|
19
19
|
LIMIT_XEMA = "limit_xema"
|
|
20
20
|
LIMIT_PREDICCIO = "limit_prediccio"
|
|
21
|
+
LIMIT_XDDE = "limit_xdde"
|
|
22
|
+
LIMIT_BASIC = "limit_basic"
|
|
23
|
+
LIMIT_QUOTA = "limit_quota"
|
|
21
24
|
STATION_STATUS = "station_status"
|
|
22
25
|
HOURLY_FORECAST_FILE_STATUS = "hourly_forecast_file_status"
|
|
23
26
|
DAILY_FORECAST_FILE_STATUS = "daily_forecast_file_status"
|
|
@@ -32,6 +35,13 @@ ALERT_COLD = "alert_cold"
|
|
|
32
35
|
ALERT_WARM = "alert_warm"
|
|
33
36
|
ALERT_WARM_NIGHT = "alert_warm_night"
|
|
34
37
|
ALERT_SNOW = "alert_snow"
|
|
38
|
+
QUOTA_FILE_STATUS = "quota_file_status"
|
|
39
|
+
QUOTA_XDDE = "quota_xdde"
|
|
40
|
+
QUOTA_PREDICCIO = "quota_prediccio"
|
|
41
|
+
QUOTA_BASIC = "quota_basic"
|
|
42
|
+
QUOTA_XEMA = "quota_xema"
|
|
43
|
+
QUOTA_QUERIES = "quota_queries"
|
|
44
|
+
LIGHTNING_FILE_STATUS = "lightning_file_status"
|
|
35
45
|
|
|
36
46
|
from homeassistant.const import Platform
|
|
37
47
|
|
|
@@ -44,6 +54,8 @@ DEFAULT_VALIDITY_DAYS = 1 # Número de días a partir de los cuales se consider
|
|
|
44
54
|
DEFAULT_VALIDITY_HOURS = 5 # Hora a partir de la cual la API tiene la información actualizada de predicciones disponible para descarga
|
|
45
55
|
DEFAULT_VALIDITY_MINUTES = 0 # Minutos a partir de los cuales la API tiene la información actualizada de predicciones disponible para descarga
|
|
46
56
|
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
|
|
57
|
+
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
|
|
58
|
+
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
|
|
47
59
|
|
|
48
60
|
# Multiplicadores para la duración de validez basada en limit_prediccio
|
|
49
61
|
ALERT_VALIDITY_MULTIPLIER_100 = 12 # para limit_prediccio <= 100
|
|
@@ -71,6 +83,8 @@ STATION_TIMESTAMP = "station_timestamp" # Código de tiempo de la estación
|
|
|
71
83
|
CONDITION = "condition" # Estado del cielo
|
|
72
84
|
MAX_TEMPERATURE_FORECAST = "max_temperature_forecast" # Temperatura máxima prevista
|
|
73
85
|
MIN_TEMPERATURE_FORECAST = "min_temperature_forecast" # Temperatura mínima prevista
|
|
86
|
+
LIGHTNING_REGION = "lightning_region" # Rayos de la comarca
|
|
87
|
+
LIGHTNING_TOWN = "lightning_town" # Rayos de la población
|
|
74
88
|
|
|
75
89
|
# Definición de códigos para variables
|
|
76
90
|
WIND_SPEED_CODE = 30
|