Compare commits

...

2 Commits

Author SHA1 Message Date
Lukas Svoboda 965f562c53
Merge pull request #92 from schizza/wslink_api_update
Update Windy integration to use new API endpoint
2026-01-30 17:17:08 +01:00
SchiZzA cf1026f2b9
Update Windy integration to use station ID and password authentication
- Replace API key with station ID and password for Windy data push
- Change Windy update URL and add authorization header
- Update config flow and constants to support new credentials
- Adjust data mapping for WSLink compatibility
- Change WSLink endpoint HTTP method to POST
2026-01-30 17:14:21 +01:00
6 changed files with 62 additions and 21 deletions

View File

@ -86,7 +86,7 @@ class WeatherDataUpdateCoordinator(DataUpdateCoordinator):
raise HTTPUnauthorized
if self.config_entry.options.get(WINDY_ENABLED):
response = await self.windy.push_data_to_windy(data)
response = await self.windy.push_data_to_windy(data, _wslink)
if self.config.options.get(POCASI_CZ_ENABLED):
await self.pocasi.push_data_to_server(data, "WSLINK" if _wslink else "WU")
@ -160,7 +160,7 @@ def register_path(
if debug:
_LOGGER.debug("Default route: %s", default_route)
wslink_route = hass.http.app.router.add_get(
wslink_route = hass.http.app.router.add_post(
WSLINK_URL,
coordinator.recieved_data if _wslink else unregistred,
name="weather_wslink_url",

View File

@ -21,9 +21,10 @@ from .const import (
POCASI_CZ_SEND_INTERVAL,
POCASI_CZ_SEND_MINIMUM,
SENSORS_TO_LOAD,
WINDY_API_KEY,
WINDY_ENABLED,
WINDY_LOGGER_ENABLED,
WINDY_STATION_ID,
WINDY_STATION_PW,
WSLINK,
)
@ -82,7 +83,8 @@ class ConfigOptionsFlowHandler(OptionsFlow):
}
self.windy_data = {
WINDY_API_KEY: self.config_entry.options.get(WINDY_API_KEY),
WINDY_STATION_ID: self.config_entry.options.get(WINDY_STATION_ID),
WINDY_STATION_PW: self.config_entry.options.get(WINDY_STATION_PW),
WINDY_ENABLED: self.config_entry.options.get(WINDY_ENABLED, False),
WINDY_LOGGER_ENABLED: self.config_entry.options.get(
WINDY_LOGGER_ENABLED, False
@ -91,7 +93,10 @@ class ConfigOptionsFlowHandler(OptionsFlow):
self.windy_data_schema = {
vol.Optional(
WINDY_API_KEY, default=self.windy_data.get(WINDY_API_KEY, "")
WINDY_STATION_ID, default=self.windy_data.get(WINDY_STATION_ID, "")
): str,
vol.Optional(
WINDY_STATION_PW, default=self.windy_data.get(WINDY_STATION_PW, "")
): str,
vol.Optional(WINDY_ENABLED, default=self.windy_data[WINDY_ENABLED]): bool
or False,
@ -192,8 +197,8 @@ class ConfigOptionsFlowHandler(OptionsFlow):
errors=errors,
)
if (user_input[WINDY_ENABLED] is True) and (user_input[WINDY_API_KEY] == ""):
errors[WINDY_API_KEY] = "windy_key_required"
if (user_input[WINDY_ENABLED] is True) and ((user_input[WINDY_STATION_ID] == "") or (user_input[WINDY_STATION_PW] == "")):
errors[WINDY_STATION_ID] = "windy_key_required"
return self.async_show_form(
step_id="windy",
data_schema=vol.Schema(self.windy_data_schema),

View File

@ -6,7 +6,7 @@ from typing import Final
DOMAIN = "sws12500"
DEFAULT_URL = "/weatherstation/updateweatherstation.php"
WSLINK_URL = "/data/upload.php"
WINDY_URL = "https://stations.windy.com/pws/update/"
WINDY_URL = "https://stations.windy.com/api/v2/observation/update"
DATABASE_PATH = "/config/home-assistant_v2.db"
POCASI_CZ_URL: Final = "http://ms.pocasimeteo.cz"
@ -36,7 +36,8 @@ POCASI_CZ_UNEXPECTED: Final = (
"Pocasti Meteo responded unexpectedly 3 times in row. Resendig is now disabled!"
)
WINDY_API_KEY = "WINDY_API_KEY"
WINDY_STATION_ID = "WINDY_STATION_ID"
WINDY_STATION_PW = "WINDY_STATION_PWD"
WINDY_ENABLED: Final = "windy_enabled_checkbox"
WINDY_LOGGER_ENABLED: Final = "windy_logger_checkbox"
WINDY_NOT_INSERTED: Final = "Data was succefuly sent to Windy, but not inserted by Windy API. Does anyone else sent data to Windy?"
@ -71,6 +72,8 @@ PURGE_DATA: Final = [
"indoortempf",
"indoorhumidity",
"dailyrainin",
"wspw",
"wsid",
]
PURGE_DATA_POCAS: Final = [

View File

@ -65,12 +65,14 @@
"description": "Přeposílání dat z metostanice na Windy",
"title": "Konfigurace Windy",
"data": {
"WINDY_API_KEY": "Klíč API KEY získaný z Windy",
"WINDY_STATION_ID": "ID stanice, získaný z Windy",
"WINDY_STATION_PWD": "Heslo stanice, získané z Windy",
"windy_enabled_checkbox": "Povolit přeposílání dat na Windy",
"windy_logger_checkbox": "Logovat data a odpovědi z Windy"
},
"data_description": {
"WINDY_API_KEY": "Klíč API KEY získaný z https://api.windy.com/keys",
"WINDY_STATION_ID": "ID stanice získaný z https://stations.windy.com/station",
"WINDY_STATION_PWD": "Heslo stanice získané z https://stations.windy.com/station",
"windy_logger_checkbox": "Zapnout pouze v případě, že chcete poslat ladící informace vývojáři."
}
},

View File

@ -60,12 +60,14 @@
"description": "Resend weather data to your Windy stations.",
"title": "Configure Windy",
"data": {
"WINDY_API_KEY": "API KEY provided by Windy",
"WINDY_STATION_ID": "Station ID obtained form Windy",
"WINDY_STATION_PWD": "Station password obtained from Windy",
"windy_enabled_checkbox": "Enable resending data to Windy",
"windy_logger_checkbox": "Log Windy data and responses"
},
"data_description": {
"WINDY_API_KEY": "Windy API KEY obtained from https://https://api.windy.com/keys",
"WINDY_STATION_ID": "Windy station ID obtained from https://stations.windy.com/stations",
"WINDY_STATION_PWD": "Windy station password obtained from https://stations.windy.com/stations",
"windy_logger_checkbox": "Enable only if you want to send debuging data to the developer."
}
},

View File

@ -11,11 +11,12 @@ from homeassistant.helpers.aiohttp_client import async_get_clientsession
from .const import (
PURGE_DATA,
WINDY_API_KEY,
WINDY_ENABLED,
WINDY_INVALID_KEY,
WINDY_LOGGER_ENABLED,
WINDY_NOT_INSERTED,
WINDY_STATION_ID,
WINDY_STATION_PW,
WINDY_SUCCESS,
WINDY_UNEXPECTED,
WINDY_URL,
@ -87,7 +88,7 @@ class WindyPush:
return None
async def push_data_to_windy(self, data):
async def push_data_to_windy(self, data, wslink: bool = False):
"""Pushes weather data do Windy stations.
Interval is 5 minutes, otherwise Windy would not accepts data.
@ -114,18 +115,46 @@ class WindyPush:
if purge in purged_data:
purged_data.pop(purge)
if "dewptf" in purged_data:
dewpoint = round(((float(purged_data.pop("dewptf")) - 32) / 1.8), 1)
purged_data["dewpoint"] = str(dewpoint)
if wslink:
# WSLink -> Windy params
if "t1ws" in purged_data:
purged_data["wind"] = purged_data.pop("t1ws")
if "t1wgust" in purged_data:
purged_data["gust"] = purged_data.pop("t1wgust")
if "t1wdir" in purged_data:
purged_data["winddir"] = purged_data.pop("t1wdir")
if "t1hum" in purged_data:
purged_data["humidity"] = purged_data.pop("t1hum")
if "t1dew" in purged_data:
purged_data["dewpoint"] = purged_data.pop("t1dew")
if "t1tem" in purged_data:
purged_data["temp"] = purged_data.pop("t1tem")
if "rbar" in purged_data:
purged_data["mbar"] = purged_data.pop("rbar")
if "t1rainhr" in purged_data:
purged_data["precip"] = purged_data.pop("t1rainhr")
if "t1uvi" in purged_data:
purged_data["uv"] = purged_data.pop("t1uvi")
if "t1solrad" in purged_data:
purged_data["solarradiation"] = purged_data.pop("t1solrad")
windy_api_key = self.config.options.get(WINDY_API_KEY)
request_url = f"{WINDY_URL}{windy_api_key}"
windy_station_id = self.config.options.get(WINDY_STATION_ID)
windy_station_pw = self.config.options.get(WINDY_STATION_PW)
request_url = f"{WINDY_URL}"
purged_data["id"] = windy_station_id
purged_data["time"] = "now"
headers = {"Authorization": f"Bearer {windy_station_pw}"}
if self.log:
_LOGGER.info("Dataset for windy: %s", purged_data)
session = async_get_clientsession(self.hass, verify_ssl=False)
try:
async with session.get(request_url, params=purged_data) as resp:
async with session.get(
request_url, params=purged_data, headers=headers
) as resp:
status = await resp.text()
try:
self.verify_windy_response(status)