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 +21 -0
- package/custom_components/meteocat/__init__.py +24 -1
- package/custom_components/meteocat/const.py +1 -0
- package/custom_components/meteocat/manifest.json +1 -1
- package/custom_components/meteocat/sensor.py +31 -42
- package/custom_components/meteocat/strings.json +4 -6
- package/custom_components/meteocat/translations/ca.json +4 -6
- package/custom_components/meteocat/translations/en.json +4 -6
- package/custom_components/meteocat/translations/es.json +4 -6
- package/custom_components/meteocat/version.py +1 -1
- package/custom_components/meteocat/weather.py +4 -0
- package/package.json +1 -1
- package/pyproject.toml +1 -1
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
|
|
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
|
|
@@ -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"
|
|
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
|
|
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
|
|
3
|
+
"version": "1.1.0",
|
|
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": {
|