meteocat 1.0.1 → 1.1.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,24 @@
1
+ # [1.1.0](https://github.com/figorr/meteocat/compare/v1.0.2...v1.1.0) (2025-01-05)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * 1.1.0 ([b0e0d9a](https://github.com/figorr/meteocat/commit/b0e0d9a3aa3d2f13bb4eff129311c8c6d4e04304))
7
+
8
+
9
+ ### Features
10
+
11
+ * add wind bearing to weather entity ([0d40460](https://github.com/figorr/meteocat/commit/0d40460947466a644a51da3bf3361e89383ccbfe))
12
+ * new wind direction cardinal sensor ([c430c48](https://github.com/figorr/meteocat/commit/c430c48a0621dbd1270a040ef017aff2c6dadc28))
13
+
14
+ ## [1.0.2](https://github.com/figorr/meteocat/compare/v1.0.1...v1.0.2) (2025-01-05)
15
+
16
+
17
+ ### Bug Fixes
18
+
19
+ * 1.0.2 ([8ec865b](https://github.com/figorr/meteocat/commit/8ec865b4d09e802bd489bc527dbfa74de5084cb7))
20
+ * include CONFIG_SCHEMA ([8911de2](https://github.com/figorr/meteocat/commit/8911de29c1804c63b79780f0bb057fdf3681eaec))
21
+
1
22
  ## [1.0.1](https://github.com/figorr/meteocat/compare/v1.0.0...v1.0.1) (2025-01-04)
2
23
 
3
24
 
@@ -1,12 +1,14 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import logging
4
+ import voluptuous as vol
4
5
  from pathlib import Path
5
6
  from homeassistant import core
6
7
  from homeassistant.config_entries import ConfigEntry
7
8
  from homeassistant.core import HomeAssistant
8
9
  from homeassistant.exceptions import HomeAssistantError
9
10
  from homeassistant.helpers.entity_platform import async_get_platforms
11
+ from homeassistant.helpers import config_validation as cv
10
12
 
11
13
  from .coordinator import (
12
14
  MeteocatSensorCoordinator,
@@ -25,7 +27,28 @@ from .const import DOMAIN, PLATFORMS
25
27
  _LOGGER = logging.getLogger(__name__)
26
28
 
27
29
  # Versión
28
- __version__ = "1.0.1"
30
+ __version__ = "1.1.0"
31
+
32
+ # Definir el esquema de configuración CONFIG_SCHEMA
33
+ CONFIG_SCHEMA = vol.Schema(
34
+ {
35
+ DOMAIN: vol.Schema(
36
+ {
37
+ vol.Required("api_key"): cv.string,
38
+ vol.Required("town_name"): cv.string,
39
+ vol.Required("town_id"): cv.string,
40
+ vol.Optional("variable_name", default="temperature"): cv.string,
41
+ vol.Optional("station_name"): cv.string,
42
+ vol.Optional("station_id"): cv.string,
43
+ vol.Optional("province_name"): cv.string,
44
+ vol.Optional("province_id"): cv.string,
45
+ vol.Optional("region_name"): cv.string,
46
+ vol.Optional("region_id"): cv.string,
47
+ }
48
+ )
49
+ },
50
+ extra=vol.ALLOW_EXTRA,
51
+ )
29
52
 
30
53
  def safe_remove(path: Path, is_folder: bool = False):
31
54
  """Elimina de forma segura un archivo o carpeta si existe."""
@@ -35,6 +35,7 @@ DEFAULT_VALIDITY_MINUTES = 0 # Minutos a partir de los cuales la API tiene la in
35
35
  # Códigos de sensores de la API
36
36
  WIND_SPEED = "wind_speed" # Velocidad del viento
37
37
  WIND_DIRECTION = "wind_direction" # Dirección del viento
38
+ WIND_DIRECTION_CARDINAL = "wind_direction_cardinal" # Dirección del viento en cardinal
38
39
  TEMPERATURE = "temperature" # Temperatura
39
40
  HUMIDITY = "humidity" # Humedad relativa
40
41
  PRESSURE = "pressure" # Presión atmosférica
@@ -9,5 +9,5 @@
9
9
  "issue_tracker": "https://github.com/figorr/meteocat/issues",
10
10
  "loggers": ["meteocatpy"],
11
11
  "requirements": ["meteocatpy==0.0.17", "packaging>=20.3", "wrapt>=1.14.0"],
12
- "version": "1.0.1"
12
+ "version": "1.1.0"
13
13
  }
@@ -36,6 +36,7 @@ from .const import (
36
36
  STATION_ID,
37
37
  WIND_SPEED,
38
38
  WIND_DIRECTION,
39
+ WIND_DIRECTION_CARDINAL,
39
40
  TEMPERATURE,
40
41
  HUMIDITY,
41
42
  PRESSURE,
@@ -107,6 +108,12 @@ SENSOR_TYPES: tuple[MeteocatSensorEntityDescription, ...] = (
107
108
  icon="mdi:compass",
108
109
  device_class=None,
109
110
  ),
111
+ MeteocatSensorEntityDescription(
112
+ key=WIND_DIRECTION_CARDINAL,
113
+ translation_key="wind_direction_cardinal",
114
+ icon="mdi:compass",
115
+ device_class=None,
116
+ ),
110
117
  MeteocatSensorEntityDescription(
111
118
  key=TEMPERATURE,
112
119
  translation_key="temperature",
@@ -290,7 +297,7 @@ async def async_setup_entry(hass, entry, async_add_entities: AddEntitiesCallback
290
297
  async_add_entities(
291
298
  MeteocatSensor(sensor_coordinator, description, entry_data)
292
299
  for description in SENSOR_TYPES
293
- if description.key in {WIND_SPEED, WIND_DIRECTION, TEMPERATURE, HUMIDITY, PRESSURE, PRECIPITATION, PRECIPITATION_ACCUMULATED, SOLAR_GLOBAL_IRRADIANCE, MAX_TEMPERATURE, MIN_TEMPERATURE, FEELS_LIKE, WIND_GUST, STATION_TIMESTAMP} # Incluir sensores generales en el coordinador SENSOR COORDINATOR
300
+ if description.key in {WIND_SPEED, WIND_DIRECTION, WIND_DIRECTION_CARDINAL, TEMPERATURE, HUMIDITY, PRESSURE, PRECIPITATION, PRECIPITATION_ACCUMULATED, SOLAR_GLOBAL_IRRADIANCE, MAX_TEMPERATURE, MIN_TEMPERATURE, FEELS_LIKE, WIND_GUST, STATION_TIMESTAMP} # Incluir sensores generales en el coordinador SENSOR COORDINATOR
294
301
  )
295
302
 
296
303
  # Sensores estáticos
@@ -657,12 +664,29 @@ class MeteocatSensor(CoordinatorEntity[MeteocatSensorCoordinator], SensorEntity)
657
664
  latest_reading = lectures[-1]
658
665
  value = latest_reading.get("valor")
659
666
 
660
- # Convertimos grados a dirección cardinal para WIND_DIRECTION
661
- if self.entity_description.key == WIND_DIRECTION and isinstance(value, (int, float)):
662
- return self._convert_degrees_to_cardinal(value)
663
-
664
667
  return value
665
668
 
669
+ # Para el sensor WIND_DIRECTION_CARDINAL, convertir grados a dirección cardinal
670
+ if self.entity_description.key == WIND_DIRECTION_CARDINAL:
671
+ stations = self.coordinator.data or []
672
+ for station in stations:
673
+ variables = station.get("variables", [])
674
+
675
+ # Filtramos por código
676
+ variable_data = next(
677
+ (var for var in variables if var.get("codi") == WIND_DIRECTION_CODE),
678
+ None,
679
+ )
680
+
681
+ if variable_data:
682
+ # Obtenemos la última lectura
683
+ lectures = variable_data.get("lectures", [])
684
+ if lectures:
685
+ latest_reading = lectures[-1]
686
+ value = latest_reading.get("valor")
687
+
688
+ return self._convert_degrees_to_cardinal(value)
689
+
666
690
  # Lógica específica para el sensor de timestamp
667
691
  if self.entity_description.key == STATION_TIMESTAMP:
668
692
  stations = self.coordinator.data or []
@@ -711,7 +735,7 @@ class MeteocatSensor(CoordinatorEntity[MeteocatSensorCoordinator], SensorEntity)
711
735
  return total_precipitation
712
736
 
713
737
  return None
714
-
738
+
715
739
  @staticmethod
716
740
  def _convert_degrees_to_cardinal(degree: float) -> str:
717
741
  """Convert degrees to cardinal direction."""
@@ -720,45 +744,10 @@ class MeteocatSensor(CoordinatorEntity[MeteocatSensorCoordinator], SensorEntity)
720
744
 
721
745
  directions = [
722
746
  "north", "north_northeast", "northeast", "east_northeast", "east", "east_southeast", "southeast", "south_southeast",
723
- "south", "south_southwest", "southwest", "west_southwest", "west", "west_northwest", "northwest", "north_northwest", "north",
747
+ "south", "south_southwest", "southwest", "west_southwest", "west", "west_northwest", "northwest", "north_northwest"
724
748
  ]
725
749
  index = round(degree / 22.5) % 16
726
750
  return directions[index]
727
-
728
- @property
729
- def extra_state_attributes(self):
730
- """Return additional attributes of the sensor."""
731
- attributes = super().extra_state_attributes or {}
732
-
733
- # Agregar grados como atributo solo para WIND_DIRECTION
734
- if self.entity_description.key == WIND_DIRECTION:
735
- # Obtener el código del sensor desde CODE_MAPPING
736
- sensor_code = self.CODE_MAPPING.get(self.entity_description.key)
737
-
738
- if sensor_code is not None:
739
- # Acceder a los datos de la estación desde el coordinator
740
- stations = self.coordinator.data or []
741
- degrees_value = None
742
-
743
- for station in stations:
744
- variables = station.get("variables", [])
745
- # Buscar la variable correspondiente al código
746
- variable_data = next(
747
- (var for var in variables if var.get("codi") == sensor_code),
748
- None,
749
- )
750
- if variable_data:
751
- # Obtener la última lectura de grados
752
- lectures = variable_data.get("lectures", [])
753
- if lectures:
754
- degrees_value = lectures[-1].get("valor")
755
- break
756
-
757
- # Asignar el valor al atributo
758
- if degrees_value is not None:
759
- attributes["degrees"] = degrees_value
760
-
761
- return attributes
762
751
 
763
752
  @property
764
753
  def device_info(self) -> DeviceInfo:
@@ -29,7 +29,10 @@
29
29
  "name": "Wind Speed"
30
30
  },
31
31
  "wind_direction": {
32
- "name": "Wind Direction",
32
+ "name": "Wind Direction"
33
+ },
34
+ "wind_direction_cardinal": {
35
+ "name": "Wind Direction Cardinal",
33
36
  "state": {
34
37
  "north": "N",
35
38
  "north_northeast": "NNE",
@@ -48,11 +51,6 @@
48
51
  "northwest": "NW",
49
52
  "north_northwest": "NNW",
50
53
  "unknown": "Unknown"
51
- },
52
- "state_attributes": {
53
- "degrees": {
54
- "name": "Degrees"
55
- }
56
54
  }
57
55
  },
58
56
  "temperature": {
@@ -29,7 +29,10 @@
29
29
  "name": "Vent Velocitat"
30
30
  },
31
31
  "wind_direction": {
32
- "name": "Vent Direcció",
32
+ "name": "Vent Direcció"
33
+ },
34
+ "wind_direction_cardinal": {
35
+ "name": "Vent Direcció Cardinal",
33
36
  "state": {
34
37
  "north": "N",
35
38
  "north_northeast": "NNE",
@@ -48,11 +51,6 @@
48
51
  "northwest": "NO",
49
52
  "north_northwest": "NNO",
50
53
  "unknown": "Desconegut"
51
- },
52
- "state_attributes": {
53
- "degrees": {
54
- "name": "Graus"
55
- }
56
54
  }
57
55
  },
58
56
  "temperature": {
@@ -29,7 +29,10 @@
29
29
  "name": "Wind Speed"
30
30
  },
31
31
  "wind_direction": {
32
- "name": "Wind Direction",
32
+ "name": "Wind Direction"
33
+ },
34
+ "wind_direction_cardinal": {
35
+ "name": "Wind Direction Cardinal",
33
36
  "state": {
34
37
  "north": "N",
35
38
  "north_northeast": "NNE",
@@ -48,11 +51,6 @@
48
51
  "northwest": "NW",
49
52
  "north_northwest": "NNW",
50
53
  "unknown": "Unknown"
51
- },
52
- "state_attributes": {
53
- "degrees": {
54
- "name": "Degrees"
55
- }
56
54
  }
57
55
  },
58
56
  "temperature": {
@@ -29,7 +29,10 @@
29
29
  "name": "Viento Velocidad"
30
30
  },
31
31
  "wind_direction": {
32
- "name": "Viento Dirección",
32
+ "name": "Viento Dirección"
33
+ },
34
+ "wind_direction_cardinal": {
35
+ "name": "Viento Dirección Cardinal",
33
36
  "state": {
34
37
  "north": "N",
35
38
  "north_northeast": "NNE",
@@ -48,11 +51,6 @@
48
51
  "northwest": "NO",
49
52
  "north_northwest": "NNO",
50
53
  "unknown": "Desconocido"
51
- },
52
- "state_attributes": {
53
- "degrees": {
54
- "name": "Grados"
55
- }
56
54
  }
57
55
  },
58
56
  "temperature": {
@@ -1,2 +1,2 @@
1
1
  # version.py
2
- __version__ = "1.0.1"
2
+ __version__ = "1.1.0"
@@ -153,6 +153,10 @@ class MeteocatWeatherEntity(CoordinatorEntity, WeatherEntity):
153
153
  @property
154
154
  def native_wind_gust_speed(self) -> Optional[float]:
155
155
  return self._get_latest_sensor_value(WIND_GUST_CODE)
156
+
157
+ @property
158
+ def wind_bearing(self) -> Optional[float]:
159
+ return self._get_latest_sensor_value(WIND_DIRECTION_CODE)
156
160
 
157
161
  @property
158
162
  def uv_index(self) -> Optional[float]:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "meteocat",
3
- "version": "1.0.1",
3
+ "version": "1.1.0",
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 = "1.0.1"
3
+ version = "1.1.0"
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"