hamsclientfork 0.2.9__tar.gz → 0.2.11__tar.gz
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.
- {hamsclientfork-0.2.9/hamsclientfork.egg-info → hamsclientfork-0.2.11}/PKG-INFO +1 -1
- {hamsclientfork-0.2.9 → hamsclientfork-0.2.11}/hamsclientfork/client.py +53 -10
- {hamsclientfork-0.2.9 → hamsclientfork-0.2.11/hamsclientfork.egg-info}/PKG-INFO +1 -1
- {hamsclientfork-0.2.9 → hamsclientfork-0.2.11}/setup.py +1 -1
- {hamsclientfork-0.2.9 → hamsclientfork-0.2.11}/.gitignore +0 -0
- {hamsclientfork-0.2.9 → hamsclientfork-0.2.11}/LICENSE +0 -0
- {hamsclientfork-0.2.9 → hamsclientfork-0.2.11}/README.md +0 -0
- {hamsclientfork-0.2.9 → hamsclientfork-0.2.11}/README.rst +0 -0
- {hamsclientfork-0.2.9 → hamsclientfork-0.2.11}/hamsclientfork/__init__.py +0 -0
- {hamsclientfork-0.2.9 → hamsclientfork-0.2.11}/hamsclientfork/__main__.py +0 -0
- {hamsclientfork-0.2.9 → hamsclientfork-0.2.11}/hamsclientfork/py.typed +0 -0
- {hamsclientfork-0.2.9 → hamsclientfork-0.2.11}/hamsclientfork.egg-info/SOURCES.txt +0 -0
- {hamsclientfork-0.2.9 → hamsclientfork-0.2.11}/hamsclientfork.egg-info/dependency_links.txt +0 -0
- {hamsclientfork-0.2.9 → hamsclientfork-0.2.11}/hamsclientfork.egg-info/requires.txt +0 -0
- {hamsclientfork-0.2.9 → hamsclientfork-0.2.11}/hamsclientfork.egg-info/top_level.txt +0 -0
- {hamsclientfork-0.2.9 → hamsclientfork-0.2.11}/setup.cfg +0 -0
- {hamsclientfork-0.2.9 → hamsclientfork-0.2.11}/tox.ini +0 -0
|
@@ -4,6 +4,7 @@ import json
|
|
|
4
4
|
import logging
|
|
5
5
|
import pandas as pd
|
|
6
6
|
import requests # type: ignore
|
|
7
|
+
import datetime
|
|
7
8
|
|
|
8
9
|
from bs4 import BeautifulSoup
|
|
9
10
|
from enum import Enum
|
|
@@ -28,7 +29,7 @@ _HEADERS = {
|
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
MS_BASE_URL = "https://www.meteosuisse.admin.ch"
|
|
31
|
-
JSON_FORECAST_URL = "https://app-prod-ws.meteoswiss-app.ch/v1/forecast?plz={}00&
|
|
32
|
+
JSON_FORECAST_URL = "https://app-prod-ws.meteoswiss-app.ch/v1/forecast?plz={}00&graph_startLowResolution=true&warning=true"
|
|
32
33
|
MS_SEARCH_URL = "https://www.meteosuisse.admin.ch/home/actualite/infos.html?ort={}&pageIndex=0&tab=search_tab"
|
|
33
34
|
CURRENT_CONDITION_URL = (
|
|
34
35
|
"https://data.geo.admin.ch/ch.meteoschweiz.messwerte-aktuell/VQHA80.csv"
|
|
@@ -70,19 +71,60 @@ def DayForecast_from_meteoswiss_data(data: dict[str, Any]) -> DayForecast:
|
|
|
70
71
|
)
|
|
71
72
|
|
|
72
73
|
|
|
74
|
+
class HourlyForecast(TypedDict):
|
|
75
|
+
time: datetime.datetime
|
|
76
|
+
temperatureMax: float
|
|
77
|
+
temperatureMean: float
|
|
78
|
+
temperatureMin: float
|
|
79
|
+
precipitationMax: float
|
|
80
|
+
precipitationMean: float
|
|
81
|
+
precipitationMin: float
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def HourlyForecast_from_meteoswiss_data(data: dict[str, Any]) -> list[HourlyForecast]:
|
|
85
|
+
time = datetime.datetime.fromtimestamp(data["start"] / 1000)
|
|
86
|
+
results: list[HourlyForecast] = []
|
|
87
|
+
for idx in range(
|
|
88
|
+
min(
|
|
89
|
+
[
|
|
90
|
+
len(data["temperatureMin1h"]),
|
|
91
|
+
len(data["temperatureMax1h"]),
|
|
92
|
+
len(data["temperatureMean1h"]),
|
|
93
|
+
len(data["precipitationMin1h"]),
|
|
94
|
+
len(data["precipitationMean1h"]),
|
|
95
|
+
len(data["precipitationMax1h"]),
|
|
96
|
+
]
|
|
97
|
+
)
|
|
98
|
+
):
|
|
99
|
+
d = HourlyForecast(
|
|
100
|
+
time=time,
|
|
101
|
+
temperatureMax=data["temperatureMax1h"][idx],
|
|
102
|
+
temperatureMean=data["temperatureMean1h"][idx],
|
|
103
|
+
temperatureMin=data["temperatureMin1h"][idx],
|
|
104
|
+
precipitationMin=data["precipitationMin1h"][idx],
|
|
105
|
+
precipitationMean=data["precipitationMean1h"][idx],
|
|
106
|
+
precipitationMax=data["precipitationMax1h"][idx],
|
|
107
|
+
)
|
|
108
|
+
results.append(d)
|
|
109
|
+
time = time + datetime.timedelta(hours=1)
|
|
110
|
+
return results
|
|
111
|
+
|
|
112
|
+
|
|
73
113
|
class Forecast(TypedDict):
|
|
74
114
|
plz: str
|
|
75
115
|
currentWeather: CurrentWeather
|
|
76
116
|
regionForecast: list[DayForecast]
|
|
117
|
+
regionHourlyForecast: list[HourlyForecast]
|
|
77
118
|
|
|
78
119
|
|
|
79
|
-
def Forecast_from_meteoswiss_data(data: dict[str, Any]):
|
|
120
|
+
def Forecast_from_meteoswiss_data(data: dict[str, Any]) -> Forecast:
|
|
80
121
|
return Forecast(
|
|
81
122
|
plz=data["plz"],
|
|
82
123
|
currentWeather=data["currentWeather"],
|
|
83
124
|
regionForecast=[
|
|
84
125
|
DayForecast_from_meteoswiss_data(x) for x in data["regionForecast"]
|
|
85
126
|
],
|
|
127
|
+
regionHourlyForecast=HourlyForecast_from_meteoswiss_data(data["graph"]),
|
|
86
128
|
)
|
|
87
129
|
|
|
88
130
|
|
|
@@ -145,7 +187,7 @@ def CurrentCondition_from_meteoswiss_data(data: dict[str, Any]) -> CurrentCondit
|
|
|
145
187
|
|
|
146
188
|
class ClientResult(TypedDict):
|
|
147
189
|
name: str
|
|
148
|
-
forecast:
|
|
190
|
+
forecast: Forecast
|
|
149
191
|
condition: list[CurrentCondition]
|
|
150
192
|
|
|
151
193
|
|
|
@@ -218,19 +260,18 @@ class meteoSwissClient:
|
|
|
218
260
|
_LOGGER.debug("End of 24 forecast udate")
|
|
219
261
|
|
|
220
262
|
def get_forecast(self):
|
|
221
|
-
_LOGGER.debug("Start update forecast data")
|
|
222
263
|
s = requests.Session()
|
|
223
264
|
# Forcing headers to avoid 500 error when downloading file
|
|
224
265
|
s.headers.update(_HEADERS)
|
|
225
266
|
|
|
226
267
|
jsonUrl = JSON_FORECAST_URL.format(self._postCode)
|
|
268
|
+
_LOGGER.debug("Start update forecast data with URL %s", jsonUrl)
|
|
227
269
|
jsonData = s.get(jsonUrl, timeout=10)
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
jsonObj = json.loads(jsonDataTxt)
|
|
270
|
+
jsonData.raise_for_status()
|
|
271
|
+
jsonObj = jsonData.json()
|
|
231
272
|
|
|
232
273
|
self._forecast = jsonObj
|
|
233
|
-
_LOGGER.debug("End of forecast
|
|
274
|
+
_LOGGER.debug("End of forecast update")
|
|
234
275
|
|
|
235
276
|
def get_current_condition(self):
|
|
236
277
|
_LOGGER.debug("Update current condition")
|
|
@@ -325,9 +366,11 @@ class meteoSwissClient:
|
|
|
325
366
|
_LOGGER.warning("Unable to find station name for : %s" % (stationId))
|
|
326
367
|
return None
|
|
327
368
|
|
|
328
|
-
def getGeoData(self, lat, lon):
|
|
369
|
+
def getGeoData(self, lat, lon, user_agent=None):
|
|
329
370
|
s = requests.Session()
|
|
330
371
|
s.headers.update(_HEADERS)
|
|
372
|
+
if user_agent:
|
|
373
|
+
s.headers.update({"User-Agent": user_agent})
|
|
331
374
|
|
|
332
375
|
uri = (
|
|
333
376
|
"https://nominatim.openstreetmap.org/reverse"
|
|
@@ -337,7 +380,7 @@ class meteoSwissClient:
|
|
|
337
380
|
geoData_req = s.get(uri)
|
|
338
381
|
try:
|
|
339
382
|
geoData_req.raise_for_status()
|
|
340
|
-
geoData = geoData_req.json
|
|
383
|
+
geoData = geoData_req.json()
|
|
341
384
|
_LOGGER.debug("Got data from OpenStreetMap: %s" % (geoData))
|
|
342
385
|
return geoData
|
|
343
386
|
except Exception:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|