Skip to content

Commit

Permalink
Add ability to show and hide weather station position on map (#134)
Browse files Browse the repository at this point in the history
  • Loading branch information
Limych committed Jul 24, 2022
1 parent 4dbf3b6 commit 312e217
Show file tree
Hide file tree
Showing 18 changed files with 180 additions and 79 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,11 @@ I put a lot of work into making this repo and component available and updated to
> **water_temperature**\
> The current temperature of water.

**show_on_map:**\
_(boolean) (Optional)_\
Enables showing the location of the weather station on the map.\
_Default value: false_

## Track updates

You can automatically track new versions of this component and update it by [HACS][hacs].
Expand Down
22 changes: 13 additions & 9 deletions custom_components/gismeteo/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,7 @@
ATTR_WEATHER_WIND_BEARING,
ATTR_WEATHER_WIND_SPEED,
)
from homeassistant.const import (
ATTR_ID,
ATTR_LATITUDE,
ATTR_LONGITUDE,
ATTR_NAME,
STATE_UNKNOWN,
)
from homeassistant.const import ATTR_ID, ATTR_NAME, STATE_UNKNOWN
from homeassistant.util import dt as dt_util

from .cache import Cache
Expand Down Expand Up @@ -168,6 +162,16 @@ def current(self):
"""Return current weather data."""
return self._current

@property
def latitude(self):
"""Return weather station latitude."""
return self._latitude

@property
def longitude(self):
"""Return weather station longitude."""
return self._longitude

@property
def attributes(self):
"""Return forecast attributes."""
Expand Down Expand Up @@ -224,9 +228,9 @@ async def async_get_location(self):
self._attributes = {
ATTR_ID: self._get(item, "id", int),
ATTR_NAME: self._get(item, "n"),
ATTR_LATITUDE: self._get(item, "lat", float),
ATTR_LONGITUDE: (lon - 360) if lon > 180 else lon,
}
self._latitude = self._get(item, "lat", float)
self._longitude = (lon - 360) if lon > 180 else lon
except (etree.ParseError, TypeError, AttributeError) as ex:
raise ApiError(
"Can't retrieve location data! Invalid server response."
Expand Down
5 changes: 5 additions & 0 deletions custom_components/gismeteo/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
CONF_MODE,
CONF_NAME,
CONF_PLATFORM,
CONF_SHOW_ON_MAP,
)
from homeassistant.core import callback

Expand Down Expand Up @@ -142,6 +143,10 @@ async def async_step_user(self, user_input=None):
CONF_FORECAST,
default=self.options.get(CONF_FORECAST, False),
): bool,
vol.Required(
CONF_SHOW_ON_MAP,
default=self.options.get(CONF_SHOW_ON_MAP, False),
): bool,
}
)
return self.async_show_form(step_id="user", data_schema=vol.Schema(schema))
Expand Down
5 changes: 4 additions & 1 deletion custom_components/gismeteo/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
# Base component constants
NAME: Final = "Gismeteo"
DOMAIN: Final = "gismeteo"
VERSION: Final = "2.4.2-alpha"
VERSION: Final = "2.5.0-alpha"
ATTRIBUTION: Final = "Data provided by Gismeteo"
ISSUE_URL: Final = "https://github.com/Limych/ha-gismeteo/issues"

Expand Down Expand Up @@ -87,6 +87,9 @@
ATTR_FORECAST_STORM: Final = ATTR_WEATHER_STORM
ATTR_FORECAST_GEOMAGNETIC_FIELD: Final = ATTR_WEATHER_GEOMAGNETIC_FIELD
ATTR_FORECAST_PHENOMENON: Final = ATTR_WEATHER_PHENOMENON
#
ATTR_LAT = "lat"
ATTR_LON = "lon"


ENDPOINT_URL: Final = "https://services.gismeteo.ru/inform-service/inf_chrome"
Expand Down
35 changes: 32 additions & 3 deletions custom_components/gismeteo/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,35 @@
For more details about this platform, please refer to the documentation at
https://github.com/Limych/ha-gismeteo/
"""
from typing import Any, Dict, Optional

from homeassistant.const import ATTR_ID
from homeassistant.const import (
ATTR_ATTRIBUTION,
ATTR_ID,
ATTR_LATITUDE,
ATTR_LONGITUDE,
CONF_SHOW_ON_MAP,
)
from homeassistant.helpers.update_coordinator import CoordinatorEntity

from . import GismeteoDataUpdateCoordinator
from .api import GismeteoApiClient
from .const import DOMAIN, NAME
from .const import ATTR_LAT, ATTR_LON, ATTRIBUTION, DOMAIN, NAME


class GismeteoEntity(CoordinatorEntity):
"""Gismeteo entity."""

def __init__(self, location_name: str, coordinator: GismeteoDataUpdateCoordinator):
def __init__(
self,
location_name: str,
coordinator: GismeteoDataUpdateCoordinator,
config: dict,
):
"""Class initialization."""
super().__init__(coordinator)
self._location_name = location_name
self._config = config

@property
def _gismeteo(self) -> GismeteoApiClient:
Expand All @@ -37,3 +50,19 @@ def device_info(self):
"manufacturer": NAME,
"model": "Forecast",
}

@property
def extra_state_attributes(self) -> Optional[Dict[str, Any]]:
"""Return the state attributes."""
attrs = self._gismeteo.attributes.copy()

if self._config.get(CONF_SHOW_ON_MAP, False):
attrs[ATTR_LATITUDE] = self._gismeteo.latitude
attrs[ATTR_LONGITUDE] = self._gismeteo.longitude
else:
attrs[ATTR_LAT] = self._gismeteo.latitude
attrs[ATTR_LON] = self._gismeteo.longitude

attrs[ATTR_ATTRIBUTION] = ATTRIBUTION

return attrs
2 changes: 1 addition & 1 deletion custom_components/gismeteo/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"domain": "gismeteo",
"name": "Gismeteo",
"version": "2.4.2-alpha",
"version": "2.5.0-alpha",
"documentation": "https://github.com/Limych/ha-gismeteo",
"issue_tracker": "https://github.com/Limych/ha-gismeteo/issues",
"dependencies": [
Expand Down
22 changes: 8 additions & 14 deletions custom_components/gismeteo/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,13 @@
"""

import logging
from typing import Any, Dict, List, Optional
from typing import List

import voluptuous as vol
from homeassistant.components.sensor import PLATFORM_SCHEMA, SensorEntity
from homeassistant.components.weather import ATTR_FORECAST_CONDITION
from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
from homeassistant.const import (
ATTR_ATTRIBUTION,
ATTR_DEVICE_CLASS,
ATTR_ICON,
ATTR_NAME,
Expand All @@ -37,7 +36,6 @@
ATTR_WEATHER_PRECIPITATION_INTENSITY,
ATTR_WEATHER_PRECIPITATION_TYPE,
ATTR_WEATHER_STORM,
ATTRIBUTION,
CONF_CACHE_DIR,
CONF_FORECAST,
CONF_YAML,
Expand Down Expand Up @@ -117,13 +115,15 @@ def _gen_entities(
config.get(CONF_MONITORED_CONDITIONS, SENSOR_TYPES.keys()),
warn=warn,
):
entities.append(GismeteoSensor(location_name, k, coordinator))
entities.append(GismeteoSensor(location_name, k, coordinator, config))
if k == "pressure":
entities.append(GismeteoSensor(location_name, "pressure_mmhg", coordinator))
entities.append(
GismeteoSensor(location_name, "pressure_mmhg", coordinator, config)
)

if config.get(CONF_FORECAST, False):
SENSOR_TYPES["forecast"] = FORECAST_SENSOR_TYPE
entities.append(GismeteoSensor(location_name, "forecast", coordinator))
entities.append(GismeteoSensor(location_name, "forecast", coordinator, config))

return entities

Expand Down Expand Up @@ -179,9 +179,10 @@ def __init__(
location_name: str,
kind: str,
coordinator: GismeteoDataUpdateCoordinator,
config: dict,
):
"""Initialize the sensor."""
super().__init__(location_name, coordinator)
super().__init__(location_name, coordinator, config)

self._kind = kind

Expand Down Expand Up @@ -255,10 +256,3 @@ def native_value(self):
_LOGGER.warning("Condition is currently not available: %s", self._kind)

return self._state

@property
def extra_state_attributes(self) -> Optional[Dict[str, Any]]:
"""Return the state attributes."""
attrs = self._gismeteo.attributes.copy()
attrs[ATTR_ATTRIBUTION] = ATTRIBUTION
return attrs
3 changes: 2 additions & 1 deletion custom_components/gismeteo/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
"platform_sensor": "Sensor entities enabled",
"platform_weather": "Weather entity enabled",
"mode": "Forecast Mode",
"forecast": "Add 3h Forecast Sensor"
"forecast": "Add 3h Forecast Sensor",
"show_on_map": "Show monitored geography on the map"
},
"title": "Gismeteo Options"
}
Expand Down
3 changes: 2 additions & 1 deletion custom_components/gismeteo/translations/pl.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
"platform_sensor": "Encje sensorów włączone",
"platform_weather": "Encja pogody włączona",
"mode": "Tryb prognozy",
"forecast": "Dodaj 3-godzinny sensor prognozy"
"forecast": "Dodaj 3-godzinny sensor prognozy",
"show_on_map": "Wy\u015bwietlaj encje na mapie"
},
"title": "Opcje Gismeteo"
}
Expand Down
3 changes: 2 additions & 1 deletion custom_components/gismeteo/translations/pt-BR.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
"platform_sensor": "Entidades do sensor ativadas",
"platform_weather": "Entidade meteorológica ativada",
"mode": "Modo de previsão",
"forecast": "Adicionar sensor de previsão de 3h"
"forecast": "Adicionar sensor de previsão de 3h",
"show_on_map": "Mostrar o monitoramento no mapa"
},
"title": "Opções do Gismeteo"
}
Expand Down
3 changes: 2 additions & 1 deletion custom_components/gismeteo/translations/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
"platform_sensor": "Сенсоры включены",
"platform_weather": "Объект weather включен",
"mode": "Режим прогноза",
"forecast": "Добавить сенсор 3-часового прогноза"
"forecast": "Добавить сенсор 3-часового прогноза",
"show_on_map": "\u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0435\u043c\u0443\u044e \u043e\u0431\u043b\u0430\u0441\u0442\u044c \u043d\u0430 \u043a\u0430\u0440\u0442\u0435"
},
"title": "Настройки Gismeteo"
}
Expand Down
28 changes: 12 additions & 16 deletions custom_components/gismeteo/weather.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,11 @@
"""

import logging
from typing import Any, Dict, Optional

import voluptuous as vol
from homeassistant.components.weather import PLATFORM_SCHEMA, WeatherEntity
from homeassistant.config_entries import SOURCE_IMPORT
from homeassistant.const import (
ATTR_ATTRIBUTION,
CONF_API_KEY,
CONF_LATITUDE,
CONF_LONGITUDE,
Expand Down Expand Up @@ -82,14 +80,14 @@ async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entitie
entities = []
if config_entry.source == SOURCE_IMPORT:
# Setup from configuration.yaml
for uid, cfg in hass.data[DOMAIN][CONF_YAML].items():
if cfg[CONF_PLATFORM] != WEATHER:
for uid, config in hass.data[DOMAIN][CONF_YAML].items():
if config[CONF_PLATFORM] != WEATHER:
continue # pragma: no cover

name = cfg[CONF_NAME]
name = config[CONF_NAME]
coordinator = hass.data[DOMAIN][uid][COORDINATOR]

entities.append(GismeteoWeather(name, coordinator))
entities.append(GismeteoWeather(name, coordinator, config))

else:
# Setup from config entry
Expand All @@ -99,17 +97,22 @@ async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entitie
name = config[CONF_NAME]
coordinator = hass.data[DOMAIN][config_entry.entry_id][COORDINATOR]

entities.append(GismeteoWeather(name, coordinator))
entities.append(GismeteoWeather(name, coordinator, config))

async_add_entities(entities, False)


class GismeteoWeather(GismeteoEntity, WeatherEntity):
"""Implementation of an Gismeteo sensor."""

def __init__(self, location_name: str, coordinator: GismeteoDataUpdateCoordinator):
def __init__(
self,
location_name: str,
coordinator: GismeteoDataUpdateCoordinator,
config: dict,
):
"""Initialize."""
super().__init__(location_name, coordinator)
super().__init__(location_name, coordinator, config)
self._attrs = {}

@property
Expand Down Expand Up @@ -176,10 +179,3 @@ def native_wind_speed_unit(self):
def forecast(self):
"""Return the forecast array."""
return self._gismeteo.forecast()

@property
def extra_state_attributes(self) -> Optional[Dict[str, Any]]:
"""Return the state attributes."""
attrs = self._gismeteo.attributes.copy()
attrs[ATTR_ATTRIBUTION] = ATTRIBUTION
return attrs
8 changes: 6 additions & 2 deletions tests/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@
from homeassistant.const import CONF_LATITUDE, CONF_LONGITUDE, CONF_NAME

MOCK_UNIQUE_ID: Final = "test_id"
MOCK_API_ID: Final = "test_api_id"

MOCK_LATITUDE: Final = 55.55
MOCK_LONGITUDE: Final = 122.12

MOCK_CONFIG: Final = {
CONF_NAME: "Home",
CONF_LATITUDE: 55.55,
CONF_LONGITUDE: 122.12,
CONF_LATITUDE: MOCK_LATITUDE,
CONF_LONGITUDE: MOCK_LONGITUDE,
}
6 changes: 2 additions & 4 deletions tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from aiohttp import ClientSession
from asynctest import CoroutineMock
from homeassistant.components.weather import ATTR_WEATHER_WIND_SPEED
from homeassistant.const import ATTR_ID, ATTR_LATITUDE, ATTR_LONGITUDE, ATTR_NAME
from homeassistant.const import ATTR_ID, ATTR_NAME
from pytest import raises
from pytest_homeassistant_custom_component.common import load_fixture

Expand Down Expand Up @@ -120,9 +120,7 @@ async def test_async_get_location():

assert gismeteo.attributes[ATTR_ID] == 167413
assert gismeteo.attributes[ATTR_NAME] == "Razvilka"
assert gismeteo._valid_coordinates(
gismeteo.attributes[ATTR_LATITUDE], gismeteo.attributes[ATTR_LONGITUDE]
)
assert gismeteo._valid_coordinates(gismeteo.latitude, gismeteo.longitude)

with patch.object(
GismeteoApiClient,
Expand Down
3 changes: 2 additions & 1 deletion tests/test_config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import pytest
from homeassistant import config_entries, data_entry_flow
from homeassistant.const import CONF_MODE, CONF_NAME, CONF_PLATFORM
from homeassistant.const import CONF_MODE, CONF_NAME, CONF_PLATFORM, CONF_SHOW_ON_MAP
from homeassistant.core import HomeAssistant
from pytest_homeassistant_custom_component.common import MockConfigEntry

Expand Down Expand Up @@ -121,4 +121,5 @@ async def test_options_flow(hass: HomeAssistant):
f"{CONF_PLATFORM}_{WEATHER}": True,
CONF_MODE: FORECAST_MODE_DAILY,
CONF_FORECAST: True,
CONF_SHOW_ON_MAP: False,
}
Loading

0 comments on commit 312e217

Please sign in to comment.