meteocat 0.1.42 → 0.1.44

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,28 @@
1
+ ## [0.1.44](https://github.com/figorr/meteocat/compare/v0.1.43...v0.1.44) (2024-12-30)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * 0.1.44 ([7a506ea](https://github.com/figorr/meteocat/commit/7a506eab7e1fa1c0975561d71520ec3e146019dd))
7
+ * add date attribute for status sensors ([5663be5](https://github.com/figorr/meteocat/commit/5663be50ba007debe349aa730a7e735f8d448a8b))
8
+ * add state translations for file status ([32bcd61](https://github.com/figorr/meteocat/commit/32bcd611cddf773046ee07043a8578a6cbc52f94))
9
+ * add translations for status sensors date attribute ([9504a58](https://github.com/figorr/meteocat/commit/9504a5809fbc83ed2bba0b507354260d6606b7c5))
10
+
11
+ ## [0.1.43](https://github.com/figorr/meteocat/compare/v0.1.42...v0.1.43) (2024-12-30)
12
+
13
+
14
+ ### Bug Fixes
15
+
16
+ * 0.1.43 ([13185b2](https://github.com/figorr/meteocat/commit/13185b2276a5efb02b4fd18d07d30ab03ca7357d))
17
+ * add info station to config_flow ([6c8c652](https://github.com/figorr/meteocat/commit/6c8c652dc54788e2b471984726dc7dd3c0ba30d6))
18
+ * add new hourly, daily and uvi file status sensors ([42aa8b2](https://github.com/figorr/meteocat/commit/42aa8b2abbf6b333287c15d92e19b69d9630e62e))
19
+ * add new hourly, daily and uvi file status sensors translations ([5639489](https://github.com/figorr/meteocat/commit/563948999feb077a5effe9c07df9dda950469d73))
20
+ * add new hourly, daily and uvi sensor constants ([f7a4814](https://github.com/figorr/meteocat/commit/f7a481435abf34926b52312cc5302045c9357e69))
21
+ * fix entity and uvi coordinator ([ee3a557](https://github.com/figorr/meteocat/commit/ee3a5571e5e08737b3393a650509732b1cd4996a))
22
+ * ignore test read json date ([f5ce2ed](https://github.com/figorr/meteocat/commit/f5ce2edfa77d1ec33c4beff8c5c775499c0564fe))
23
+ * include entity and uvi coordinators ([4128d39](https://github.com/figorr/meteocat/commit/4128d3902bd67414eaee6d8d6da4628ecbce3493))
24
+ * set region, province and status to str ([31f58e7](https://github.com/figorr/meteocat/commit/31f58e7d701b2499e4f4d9f385238368703c75ff))
25
+
1
26
  ## [0.1.42](https://github.com/figorr/meteocat/compare/v0.1.41...v0.1.42) (2024-12-28)
2
27
 
3
28
 
@@ -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.42"
28
+ __version__ = "0.1.44"
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."""
@@ -53,7 +53,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
53
53
  # Validar campos requeridos
54
54
  required_fields = [
55
55
  "api_key", "town_name", "town_id", "variable_name",
56
- "variable_id", "station_name", "station_id"
56
+ "variable_id", "station_name", "station_id", "province_name",
57
+ "province_id", "region_name", "region_id"
57
58
  ]
58
59
  missing_fields = [field for field in required_fields if field not in entry_data]
59
60
  if missing_fields:
@@ -63,7 +64,9 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
63
64
  _LOGGER.debug(
64
65
  f"Datos de configuración: Municipio '{entry_data['town_name']}' (ID: {entry_data['town_id']}), "
65
66
  f"Variable '{entry_data['variable_name']}' (ID: {entry_data['variable_id']}), "
66
- f"Estación '{entry_data['station_name']}' (ID: {entry_data['station_id']})."
67
+ f"Estación '{entry_data['station_name']}' (ID: {entry_data['station_id']}), "
68
+ f"Provincia '{entry_data['province_name']}' (ID: {entry_data['province_id']}), "
69
+ f"Comarca '{entry_data['region_name']}' (ID: {entry_data['region_id']})."
67
70
  )
68
71
 
69
72
  # Inicializar coordinadores
@@ -23,7 +23,16 @@ from .const import (
23
23
  VARIABLE_NAME,
24
24
  VARIABLE_ID,
25
25
  STATION_NAME,
26
- STATION_ID
26
+ STATION_ID,
27
+ STATION_TYPE,
28
+ LATITUDE,
29
+ LONGITUDE,
30
+ ALTITUDE,
31
+ REGION_ID,
32
+ REGION_NAME,
33
+ PROVINCE_ID,
34
+ PROVINCE_NAME,
35
+ STATION_STATUS
27
36
  )
28
37
 
29
38
  from .options_flow import MeteocatOptionsFlowHandler
@@ -31,6 +40,8 @@ from meteocatpy.town import MeteocatTown
31
40
  from meteocatpy.symbols import MeteocatSymbols
32
41
  from meteocatpy.variables import MeteocatVariables
33
42
  from meteocatpy.townstations import MeteocatTownStations
43
+ from meteocatpy.infostation import MeteocatInfoStation
44
+
34
45
  from meteocatpy.exceptions import BadRequestError, ForbiddenError, TooManyRequestsError, InternalServerError, UnknownAPIError
35
46
 
36
47
  _LOGGER = logging.getLogger(__name__)
@@ -103,10 +114,17 @@ class MeteocatConfigFlow(ConfigFlow, domain=DOMAIN):
103
114
  errors = {}
104
115
 
105
116
  # Crear directorio de activos (assets) si no existe
106
- assets_dir = Path(__file__).parent / "assets"
107
- assets_dir.mkdir(parents=True, exist_ok=True)
108
- symbols_file = assets_dir / "symbols.json"
109
- variables_file = assets_dir / "variables.json"
117
+ assets_dir = os.path.join(
118
+ self.hass.config.path(),
119
+ "custom_components",
120
+ "meteocat",
121
+ "assets"
122
+ )
123
+ os.makedirs(assets_dir, exist_ok=True)
124
+
125
+ # Rutas para los archivos de símbolos y variables
126
+ symbols_file = os.path.join(assets_dir, "symbols.json")
127
+ variables_file = os.path.join(assets_dir, "variables.json")
110
128
 
111
129
  try:
112
130
  # Descargar y guardar los símbolos
@@ -171,6 +189,26 @@ class MeteocatConfigFlow(ConfigFlow, domain=DOMAIN):
171
189
  self.station_id = selected_station["codi"]
172
190
  self.station_name = selected_station["nom"]
173
191
 
192
+ # Obtener metadatos de la estación
193
+ infostation_client = MeteocatInfoStation(self.api_key)
194
+ try:
195
+ station_metadata = await infostation_client.get_infostation(self.station_id)
196
+ except Exception as ex:
197
+ _LOGGER.error("Error al obtener los metadatos de la estación: %s", ex)
198
+ errors["base"] = "metadata_fetch_failed"
199
+ station_metadata = {}
200
+
201
+ # Extraer los valores necesarios de los metadatos
202
+ self.station_type = station_metadata.get("tipus", "")
203
+ self.latitude = station_metadata.get("coordenades", {}).get("latitud", 0.0)
204
+ self.longitude = station_metadata.get("coordenades", {}).get("longitud", 0.0)
205
+ self.altitude = station_metadata.get("altitud", 0)
206
+ self.region_id = station_metadata.get("comarca", {}).get("codi", "")
207
+ self.region_name = station_metadata.get("comarca", {}).get("nom", "")
208
+ self.province_id = station_metadata.get("provincia", {}).get("codi", "")
209
+ self.province_name = station_metadata.get("provincia", {}).get("nom", "")
210
+ self.station_status = station_metadata.get("estats", [{}])[0].get("codi", "")
211
+
174
212
  return self.async_create_entry(
175
213
  title=self.selected_municipi["nom"],
176
214
  data={
@@ -180,7 +218,16 @@ class MeteocatConfigFlow(ConfigFlow, domain=DOMAIN):
180
218
  VARIABLE_NAME: "Temperatura",
181
219
  VARIABLE_ID: str(self.variable_id),
182
220
  STATION_NAME: self.station_name,
183
- STATION_ID: self.station_id
221
+ STATION_ID: self.station_id,
222
+ STATION_TYPE: self.station_type,
223
+ LATITUDE: self.latitude,
224
+ LONGITUDE: self.longitude,
225
+ ALTITUDE: self.altitude,
226
+ REGION_ID: str(self.region_id),
227
+ REGION_NAME: self.region_name,
228
+ PROVINCE_ID: str(self.province_id),
229
+ PROVINCE_NAME: self.province_name,
230
+ STATION_STATUS: str(self.station_status),
184
231
  },
185
232
  )
186
233
  else:
@@ -8,6 +8,18 @@ VARIABLE_NAME = "variable_name"
8
8
  VARIABLE_ID = "variable_id"
9
9
  STATION_NAME = "station_name"
10
10
  STATION_ID = "station_id"
11
+ STATION_TYPE = "station_type"
12
+ LATITUDE = "latitude"
13
+ LONGITUDE = "longitude"
14
+ ALTITUDE = "altitude"
15
+ REGION_ID = "region_id"
16
+ REGION_NAME = "region_name"
17
+ PROVINCE_ID = "province_id"
18
+ PROVINCE_NAME = "province_name"
19
+ STATION_STATUS = "station_status"
20
+ HOURLY_FORECAST_FILE_STATUS = "hourly_forecast_file_status"
21
+ DAILY_FORECAST_FILE_STATUS = "daily_forecast_file_status"
22
+ UVI_FILE_STATUS = "uvi_file_status"
11
23
 
12
24
  from homeassistant.const import Platform
13
25
 
@@ -275,22 +275,15 @@ class MeteocatUviCoordinator(DataUpdateCoordinator):
275
275
  """Comprueba si el archivo JSON contiene datos válidos para el día actual y devuelve los datos si son válidos."""
276
276
  try:
277
277
  if not os.path.exists(self.uvi_file):
278
+ _LOGGER.info("El archivo %s no existe. Se considerará inválido.", self.uvi_file)
278
279
  return None
279
280
 
280
281
  async with aiofiles.open(self.uvi_file, "r", encoding="utf-8") as file:
281
282
  content = await file.read()
282
283
  data = json.loads(content)
283
284
 
284
- # Verificar que el formato sea correcto
285
- if not isinstance(data, dict) or "uvi" not in data:
286
- return None
287
-
288
- uvi_data = data["uvi"]
289
- if not isinstance(uvi_data, list) or not uvi_data:
290
- return None
291
-
292
285
  # Validar la fecha del primer elemento superior a 1 día
293
- first_date = datetime.strptime(uvi_data[0].get("date"), "%Y-%m-%d").date()
286
+ first_date = datetime.strptime(data["uvi"][0].get("date"), "%Y-%m-%d").date()
294
287
  today = datetime.now(timezone.utc).date()
295
288
 
296
289
  # Log detallado
@@ -319,7 +312,7 @@ class MeteocatUviCoordinator(DataUpdateCoordinator):
319
312
  try:
320
313
  # Validar el archivo JSON existente
321
314
  valid_data = await self.is_uvi_data_valid()
322
- if valid_data and "uvi" in valid_data:
315
+ if valid_data:
323
316
  _LOGGER.info("Los datos del índice UV están actualizados. No se realiza llamada a la API.")
324
317
  return valid_data['uvi']
325
318
 
@@ -511,9 +504,7 @@ class MeteocatEntityCoordinator(DataUpdateCoordinator):
511
504
  async with aiofiles.open(file_path, "r", encoding="utf-8") as f:
512
505
  content = await f.read()
513
506
  data = json.loads(content)
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
507
+
517
508
  # Obtener la fecha del primer día
518
509
  first_date = datetime.fromisoformat(data["dies"][0]["data"].rstrip("Z")).date()
519
510
  today = datetime.now(timezone.utc).date()
@@ -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.16", "packaging>=20.3", "wrapt>=1.14.0"],
11
- "version": "0.1.42"
10
+ "requirements": ["meteocatpy==0.0.17", "packaging>=20.3", "wrapt>=1.14.0"],
11
+ "version": "0.1.44"
12
12
  }
@@ -1,7 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from dataclasses import dataclass
4
- from datetime import datetime
4
+ from datetime import datetime, timezone
5
5
  import logging
6
6
  from homeassistant.helpers.entity import (
7
7
  DeviceInfo,
@@ -48,6 +48,9 @@ from .const import (
48
48
  CONDITION,
49
49
  MAX_TEMPERATURE_FORECAST,
50
50
  MIN_TEMPERATURE_FORECAST,
51
+ HOURLY_FORECAST_FILE_STATUS,
52
+ DAILY_FORECAST_FILE_STATUS,
53
+ UVI_FILE_STATUS,
51
54
  WIND_SPEED_CODE,
52
55
  WIND_DIRECTION_CODE,
53
56
  TEMPERATURE_CODE,
@@ -68,6 +71,8 @@ from .coordinator import (
68
71
  MeteocatUviFileCoordinator,
69
72
  MeteocatConditionCoordinator,
70
73
  MeteocatTempForecastCoordinator,
74
+ MeteocatEntityCoordinator,
75
+ MeteocatUviCoordinator,
71
76
  )
72
77
 
73
78
  _LOGGER = logging.getLogger(__name__)
@@ -229,6 +234,24 @@ SENSOR_TYPES: tuple[MeteocatSensorEntityDescription, ...] = (
229
234
  state_class=SensorStateClass.MEASUREMENT,
230
235
  native_unit_of_measurement=UnitOfTemperature.CELSIUS,
231
236
  ),
237
+ MeteocatSensorEntityDescription(
238
+ key=HOURLY_FORECAST_FILE_STATUS,
239
+ translation_key="hourly_forecast_file_status",
240
+ icon="mdi:clock",
241
+ entity_category=EntityCategory.DIAGNOSTIC,
242
+ ),
243
+ MeteocatSensorEntityDescription(
244
+ key=DAILY_FORECAST_FILE_STATUS,
245
+ translation_key="daily_forecast_file_status",
246
+ icon="mdi:clock",
247
+ entity_category=EntityCategory.DIAGNOSTIC,
248
+ ),
249
+ MeteocatSensorEntityDescription(
250
+ key=UVI_FILE_STATUS,
251
+ translation_key="uvi_file_status",
252
+ icon="mdi:clock",
253
+ entity_category=EntityCategory.DIAGNOSTIC,
254
+ )
232
255
  )
233
256
 
234
257
  @callback
@@ -242,12 +265,14 @@ async def async_setup_entry(hass, entry, async_add_entities: AddEntitiesCallback
242
265
  static_sensor_coordinator = entry_data.get("static_sensor_coordinator")
243
266
  condition_coordinator = entry_data.get("condition_coordinator")
244
267
  temp_forecast_coordinator = entry_data.get("temp_forecast_coordinator")
268
+ entity_coordinator = entry_data.get("entity_coordinator")
269
+ uvi_coordinator = entry_data.get("uvi_coordinator")
245
270
 
246
271
  # Sensores generales
247
272
  async_add_entities(
248
273
  MeteocatSensor(coordinator, description, entry_data)
249
274
  for description in SENSOR_TYPES
250
- if description.key not in {TOWN_NAME, TOWN_ID, STATION_NAME, STATION_ID, UV_INDEX, CONDITION, MAX_TEMPERATURE_FORECAST, MIN_TEMPERATURE_FORECAST} # Excluir estáticos y UVI
275
+ if description.key not in {TOWN_NAME, TOWN_ID, STATION_NAME, STATION_ID, UV_INDEX, CONDITION, MAX_TEMPERATURE_FORECAST, MIN_TEMPERATURE_FORECAST, HOURLY_FORECAST_FILE_STATUS, DAILY_FORECAST_FILE_STATUS, UVI_FILE_STATUS} # Excluir estáticos y UVI
251
276
  )
252
277
 
253
278
  # Sensores estáticos
@@ -278,6 +303,27 @@ async def async_setup_entry(hass, entry, async_add_entities: AddEntitiesCallback
278
303
  if description.key in {MAX_TEMPERATURE_FORECAST, MIN_TEMPERATURE_FORECAST}
279
304
  )
280
305
 
306
+ # Sensores de estado de los archivos de previsión horaria
307
+ async_add_entities(
308
+ MeteocatHourlyForecastStatusSensor(entity_coordinator, description, entry_data)
309
+ for description in SENSOR_TYPES
310
+ if description.key == HOURLY_FORECAST_FILE_STATUS
311
+ )
312
+
313
+ # Sensores de estado de los archivos de previsión diaria
314
+ async_add_entities(
315
+ MeteocatDailyForecastStatusSensor(entity_coordinator, description, entry_data)
316
+ for description in SENSOR_TYPES
317
+ if description.key == DAILY_FORECAST_FILE_STATUS
318
+ )
319
+
320
+ # Sensores de estado de los archivos de uvi
321
+ async_add_entities(
322
+ MeteocatUviStatusSensor(uvi_coordinator, description, entry_data)
323
+ for description in SENSOR_TYPES
324
+ if description.key == UVI_FILE_STATUS
325
+ )
326
+
281
327
  class MeteocatStaticSensor(CoordinatorEntity[MeteocatStaticSensorCoordinator], SensorEntity):
282
328
  """Representation of a static Meteocat sensor."""
283
329
  STATIC_KEYS = {TOWN_NAME, TOWN_ID, STATION_NAME, STATION_ID}
@@ -718,3 +764,155 @@ class MeteocatTempForecast(CoordinatorEntity[MeteocatTempForecastCoordinator], S
718
764
  manufacturer="Meteocat",
719
765
  model="Meteocat API",
720
766
  )
767
+
768
+ class MeteocatHourlyForecastStatusSensor(CoordinatorEntity[MeteocatEntityCoordinator], SensorEntity):
769
+
770
+ _attr_has_entity_name = True # Activa el uso de nombres basados en el dispositivo
771
+
772
+ def __init__(self, entity_coordinator, description, entry_data):
773
+ super().__init__(entity_coordinator)
774
+ self.entity_description = description
775
+ self._town_name = entry_data["town_name"]
776
+ self._town_id = entry_data["town_id"]
777
+ self._station_id = entry_data["station_id"]
778
+
779
+ # Unique ID for the entity
780
+ self._attr_unique_id = f"sensor.{DOMAIN}_{self._station_id}_hourly_status"
781
+
782
+ # Assign entity_category if defined in the description
783
+ self._attr_entity_category = getattr(description, "entity_category", None)
784
+
785
+ def _get_first_date(self):
786
+ hourly_data = self.coordinator.data.get("hourly")
787
+ if hourly_data and "dies" in hourly_data:
788
+ return datetime.fromisoformat(hourly_data["dies"][0]["data"].rstrip("Z")).date()
789
+ return None
790
+
791
+ @property
792
+ def native_value(self):
793
+ first_date = self._get_first_date()
794
+ if first_date:
795
+ today = datetime.now(timezone.utc).date()
796
+ days_difference = (today - first_date).days
797
+ _LOGGER.debug(f"Diferencia de días para predicciones horarias: {days_difference}")
798
+ return "updated" if days_difference <= 1 else "obsolete"
799
+ return "unknown"
800
+
801
+ @property
802
+ def extra_state_attributes(self):
803
+ attributes = super().extra_state_attributes or {}
804
+ first_date = self._get_first_date()
805
+ if first_date:
806
+ attributes["update_date"] = first_date.isoformat()
807
+ return attributes
808
+
809
+ @property
810
+ def device_info(self) -> DeviceInfo:
811
+ """Return the device info."""
812
+ return DeviceInfo(
813
+ identifiers={(DOMAIN, self._town_id)},
814
+ name="Meteocat " + self._station_id + " " + self._town_name,
815
+ manufacturer="Meteocat",
816
+ model="Meteocat API",
817
+ )
818
+
819
+ class MeteocatDailyForecastStatusSensor(CoordinatorEntity[MeteocatEntityCoordinator], SensorEntity):
820
+
821
+ _attr_has_entity_name = True # Activa el uso de nombres basados en el dispositivo
822
+
823
+ def __init__(self, entity_coordinator, description, entry_data):
824
+ super().__init__(entity_coordinator)
825
+ self.entity_description = description
826
+ self._town_name = entry_data["town_name"]
827
+ self._town_id = entry_data["town_id"]
828
+ self._station_id = entry_data["station_id"]
829
+
830
+ # Unique ID for the entity
831
+ self._attr_unique_id = f"sensor.{DOMAIN}_{self._station_id}_daily_status"
832
+
833
+ # Assign entity_category if defined in the description
834
+ self._attr_entity_category = getattr(description, "entity_category", None)
835
+
836
+ def _get_first_date(self):
837
+ daily_data = self.coordinator.data.get("daily")
838
+ if daily_data and "dies" in daily_data:
839
+ return datetime.fromisoformat(daily_data["dies"][0]["data"].rstrip("Z")).date()
840
+ return None
841
+
842
+ @property
843
+ def native_value(self):
844
+ first_date = self._get_first_date()
845
+ if first_date:
846
+ today = datetime.now(timezone.utc).date()
847
+ days_difference = (today - first_date).days
848
+ _LOGGER.debug(f"Diferencia de días para predicciones diarias: {days_difference}")
849
+ return "updated" if days_difference <= 1 else "obsolete"
850
+ return "unknown"
851
+
852
+ @property
853
+ def extra_state_attributes(self):
854
+ attributes = super().extra_state_attributes or {}
855
+ first_date = self._get_first_date()
856
+ if first_date:
857
+ attributes["update_date"] = first_date.isoformat()
858
+ return attributes
859
+
860
+ @property
861
+ def device_info(self) -> DeviceInfo:
862
+ """Return the device info."""
863
+ return DeviceInfo(
864
+ identifiers={(DOMAIN, self._town_id)},
865
+ name="Meteocat " + self._station_id + " " + self._town_name,
866
+ manufacturer="Meteocat",
867
+ model="Meteocat API",
868
+ )
869
+
870
+ class MeteocatUviStatusSensor(CoordinatorEntity[MeteocatUviCoordinator], SensorEntity):
871
+
872
+ _attr_has_entity_name = True # Activa el uso de nombres basados en el dispositivo
873
+
874
+ def __init__(self, uvi_coordinator, description, entry_data):
875
+ super().__init__(uvi_coordinator)
876
+ self.entity_description = description
877
+ self._town_name = entry_data["town_name"]
878
+ self._town_id = entry_data["town_id"]
879
+ self._station_id = entry_data["station_id"]
880
+
881
+ # Unique ID for the entity
882
+ self._attr_unique_id = f"sensor.{DOMAIN}_{self._station_id}_uvi_status"
883
+
884
+ # Assign entity_category if defined in the description
885
+ self._attr_entity_category = getattr(description, "entity_category", None)
886
+
887
+ def _get_first_date(self):
888
+ if self.coordinator.data:
889
+ return datetime.strptime(self.coordinator.data[0].get("date"), "%Y-%m-%d").date()
890
+ return None
891
+
892
+ @property
893
+ def native_value(self):
894
+ first_date = self._get_first_date()
895
+ if first_date:
896
+ today = datetime.now(timezone.utc).date()
897
+ days_difference = (today - first_date).days
898
+ _LOGGER.debug(f"Diferencia de días para UVI: {days_difference}")
899
+ return "updated" if days_difference <= 1 else "obsolete"
900
+ return "unknown"
901
+
902
+ @property
903
+ def extra_state_attributes(self):
904
+ attributes = super().extra_state_attributes or {}
905
+ first_date = self._get_first_date()
906
+ if first_date:
907
+ attributes["update_date"] = first_date.isoformat()
908
+ return attributes
909
+
910
+ @property
911
+ def device_info(self) -> DeviceInfo:
912
+ """Return the device info."""
913
+ return DeviceInfo(
914
+ identifiers={(DOMAIN, self._town_id)},
915
+ name="Meteocat " + self._station_id + " " + self._town_name,
916
+ manufacturer="Meteocat",
917
+ model="Meteocat API",
918
+ )
@@ -133,8 +133,43 @@
133
133
  },
134
134
  "min_temperature_forecast": {
135
135
  "name": "Min Temperature Today"
136
+ },
137
+ "hourly_forecast_file_status": {
138
+ "name": "Hourly File",
139
+ "state": {
140
+ "updated": "Updated",
141
+ "obsolete": "Obsolete"
142
+ },
143
+ "state_attributes": {
144
+ "update_date": {
145
+ "name": "Date"
146
+ }
147
+ }
148
+ },
149
+ "daily_forecast_file_status": {
150
+ "name": "Daily File",
151
+ "state": {
152
+ "updated": "Updated",
153
+ "obsolete": "Obsolete"
154
+ },
155
+ "state_attributes": {
156
+ "update_date": {
157
+ "name": "Date"
158
+ }
159
+ }
160
+ },
161
+ "uvi_file_status": {
162
+ "name": "Uvi File",
163
+ "state": {
164
+ "updated": "Updated",
165
+ "obsolete": "Obsolete"
166
+ },
167
+ "state_attributes": {
168
+ "update_date": {
169
+ "name": "Date"
170
+ }
171
+ }
136
172
  }
137
173
  }
138
174
  }
139
175
  }
140
-
@@ -133,6 +133,42 @@
133
133
  },
134
134
  "min_temperature_forecast": {
135
135
  "name": "Temperatura Min Avui"
136
+ },
137
+ "hourly_forecast_file_status": {
138
+ "name": "Arxiu Horari",
139
+ "state": {
140
+ "updated": "Actualitzat",
141
+ "obsolete": "Obsolet"
142
+ },
143
+ "state_attributes": {
144
+ "update_date": {
145
+ "name": "Data"
146
+ }
147
+ }
148
+ },
149
+ "daily_forecast_file_status": {
150
+ "name": "Arxiu Diari",
151
+ "state": {
152
+ "updated": "Actualitzat",
153
+ "obsolete": "Obsolet"
154
+ },
155
+ "state_attributes": {
156
+ "update_date": {
157
+ "name": "Data"
158
+ }
159
+ }
160
+ },
161
+ "uvi_file_status": {
162
+ "name": "Arxiu UVI",
163
+ "state": {
164
+ "updated": "Actualitzat",
165
+ "obsolete": "Obsolet"
166
+ },
167
+ "state_attributes": {
168
+ "update_date": {
169
+ "name": "Data"
170
+ }
171
+ }
136
172
  }
137
173
  }
138
174
  }
@@ -133,6 +133,42 @@
133
133
  },
134
134
  "min_temperature_forecast": {
135
135
  "name": "Min Temperature Today"
136
+ },
137
+ "hourly_forecast_file_status": {
138
+ "name": "Hourly File",
139
+ "state": {
140
+ "updated": "Updated",
141
+ "obsolete": "Obsolete"
142
+ },
143
+ "state_attributes": {
144
+ "update_date": {
145
+ "name": "Date"
146
+ }
147
+ }
148
+ },
149
+ "daily_forecast_file_status": {
150
+ "name": "Daily File",
151
+ "state": {
152
+ "updated": "Updated",
153
+ "obsolete": "Obsolete"
154
+ },
155
+ "state_attributes": {
156
+ "update_date": {
157
+ "name": "Date"
158
+ }
159
+ }
160
+ },
161
+ "uvi_file_status": {
162
+ "name": "Uvi File",
163
+ "state": {
164
+ "updated": "Updated",
165
+ "obsolete": "Obsolete"
166
+ },
167
+ "state_attributes": {
168
+ "update_date": {
169
+ "name": "Date"
170
+ }
171
+ }
136
172
  }
137
173
  }
138
174
  }
@@ -133,8 +133,43 @@
133
133
  },
134
134
  "min_temperature_forecast": {
135
135
  "name": "Temperatura Min Hoy"
136
+ },
137
+ "hourly_forecast_file_status": {
138
+ "name": "Archivo Horario",
139
+ "state": {
140
+ "updated": "Actualizado",
141
+ "obsolete": "Obsoleto"
142
+ },
143
+ "state_attributes": {
144
+ "update_date": {
145
+ "name": "Fecha"
146
+ }
147
+ }
148
+ },
149
+ "daily_forecast_file_status": {
150
+ "name": "Archivo Diario",
151
+ "state": {
152
+ "updated": "Actualizado",
153
+ "obsolete": "Obsoleto"
154
+ },
155
+ "state_attributes": {
156
+ "update_date": {
157
+ "name": "Fecha"
158
+ }
159
+ }
160
+ },
161
+ "uvi_file_status": {
162
+ "name": "Archivo UVI",
163
+ "state": {
164
+ "updated": "Actualizado",
165
+ "obsolete": "Obsoleto"
166
+ },
167
+ "state_attributes": {
168
+ "update_date": {
169
+ "name": "Fecha"
170
+ }
171
+ }
136
172
  }
137
173
  }
138
174
  }
139
175
  }
140
-
@@ -1,2 +1,2 @@
1
1
  # version.py
2
- __version__ = "0.1.42"
2
+ __version__ = "0.1.44"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "meteocat",
3
- "version": "0.1.42",
3
+ "version": "0.1.44",
4
4
  "description": "[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)\r [![Python version compatibility](https://img.shields.io/pypi/pyversions/meteocat)](https://pypi.org/project/meteocat)\r [![pipeline status](https://gitlab.com/figorr/meteocat/badges/master/pipeline.svg)](https://gitlab.com/figorr/meteocat/commits/master)",
5
5
  "main": "index.js",
6
6
  "directories": {
package/pyproject.toml CHANGED
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "meteocat"
3
- version = "0.1.42"
3
+ version = "0.1.44"
4
4
  description = "Script para obtener datos meteorológicos de la API de Meteocat"
5
5
  authors = ["figorr <jdcuartero@yahoo.es>"]
6
6
  license = "Apache-2.0"