hamsclientfork 0.2.7__tar.gz → 0.2.9__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.7/hamsclientfork.egg-info → hamsclientfork-0.2.9}/PKG-INFO +5 -1
- {hamsclientfork-0.2.7 → hamsclientfork-0.2.9}/hamsclientfork/client.py +146 -34
- hamsclientfork-0.2.9/hamsclientfork/py.typed +0 -0
- {hamsclientfork-0.2.7 → hamsclientfork-0.2.9/hamsclientfork.egg-info}/PKG-INFO +5 -1
- {hamsclientfork-0.2.7 → hamsclientfork-0.2.9}/hamsclientfork.egg-info/SOURCES.txt +1 -0
- {hamsclientfork-0.2.7 → hamsclientfork-0.2.9}/setup.py +1 -1
- {hamsclientfork-0.2.7 → hamsclientfork-0.2.9}/.gitignore +0 -0
- {hamsclientfork-0.2.7 → hamsclientfork-0.2.9}/LICENSE +0 -0
- {hamsclientfork-0.2.7 → hamsclientfork-0.2.9}/README.md +0 -0
- {hamsclientfork-0.2.7 → hamsclientfork-0.2.9}/README.rst +0 -0
- {hamsclientfork-0.2.7 → hamsclientfork-0.2.9}/hamsclientfork/__init__.py +0 -0
- {hamsclientfork-0.2.7 → hamsclientfork-0.2.9}/hamsclientfork/__main__.py +0 -0
- {hamsclientfork-0.2.7 → hamsclientfork-0.2.9}/hamsclientfork.egg-info/dependency_links.txt +0 -0
- {hamsclientfork-0.2.7 → hamsclientfork-0.2.9}/hamsclientfork.egg-info/requires.txt +0 -0
- {hamsclientfork-0.2.7 → hamsclientfork-0.2.9}/hamsclientfork.egg-info/top_level.txt +0 -0
- {hamsclientfork-0.2.7 → hamsclientfork-0.2.9}/setup.cfg +0 -0
- {hamsclientfork-0.2.7 → hamsclientfork-0.2.9}/tox.ini +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: hamsclientfork
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.9
|
|
4
4
|
Summary: Library to get data from meteo swiss
|
|
5
5
|
Home-page: https://github.com/Rudd-O/hamsclientfork
|
|
6
6
|
Author: websylv
|
|
@@ -15,6 +15,10 @@ Classifier: Programming Language :: Python :: 3.9
|
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.10
|
|
16
16
|
Classifier: Programming Language :: Python :: 3.11
|
|
17
17
|
License-File: LICENSE
|
|
18
|
+
Requires-Dist: requests>=2.22.0
|
|
19
|
+
Requires-Dist: pandas>=0.25.3
|
|
20
|
+
Requires-Dist: beautifulsoup4>=4.8.2
|
|
21
|
+
Requires-Dist: geopy>=2.0.0
|
|
18
22
|
|
|
19
23
|
meteoswiss
|
|
20
24
|
==========
|
|
@@ -3,11 +3,11 @@ import geopy.distance
|
|
|
3
3
|
import json
|
|
4
4
|
import logging
|
|
5
5
|
import pandas as pd
|
|
6
|
-
import requests
|
|
6
|
+
import requests # type: ignore
|
|
7
7
|
|
|
8
8
|
from bs4 import BeautifulSoup
|
|
9
9
|
from enum import Enum
|
|
10
|
-
from typing import Any
|
|
10
|
+
from typing import Any, TypedDict
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
class StationType(str, Enum):
|
|
@@ -19,6 +19,14 @@ class StationType(str, Enum):
|
|
|
19
19
|
|
|
20
20
|
_LOGGER = logging.getLogger(__name__)
|
|
21
21
|
|
|
22
|
+
_HEADERS = {
|
|
23
|
+
"Accept": "text/html,application/xhtml+xml,application/xml;"
|
|
24
|
+
"q=0.9,image/webp,*/*;q=0.8",
|
|
25
|
+
"Accept-Encoding": "gzip, deflate, sdch",
|
|
26
|
+
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML"
|
|
27
|
+
", like Gecko) Chrome/1337 Safari/537.36",
|
|
28
|
+
}
|
|
29
|
+
|
|
22
30
|
MS_BASE_URL = "https://www.meteosuisse.admin.ch"
|
|
23
31
|
JSON_FORECAST_URL = "https://app-prod-ws.meteoswiss-app.ch/v1/forecast?plz={}00&graph=false&warning=true"
|
|
24
32
|
MS_SEARCH_URL = "https://www.meteosuisse.admin.ch/home/actualite/infos.html?ort={}&pageIndex=0&tab=search_tab"
|
|
@@ -35,6 +43,120 @@ MS_24FORECAST_URL = (
|
|
|
35
43
|
MS_24FORECAST_REF = "https://www.meteosuisse.admin.ch//content/meteoswiss/fr/home.mobile.meteo-products--overview.html"
|
|
36
44
|
|
|
37
45
|
|
|
46
|
+
class CurrentWeather(TypedDict):
|
|
47
|
+
time: int
|
|
48
|
+
icon: int
|
|
49
|
+
iconV2: int
|
|
50
|
+
temperature: float
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class DayForecast(TypedDict):
|
|
54
|
+
dayDate: str
|
|
55
|
+
iconDay: int
|
|
56
|
+
iconDayV2: int
|
|
57
|
+
temperatureMax: float
|
|
58
|
+
temperatureMin: float
|
|
59
|
+
precipitation: float
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def DayForecast_from_meteoswiss_data(data: dict[str, Any]) -> DayForecast:
|
|
63
|
+
return DayForecast(
|
|
64
|
+
dayDate=data["dayDate"],
|
|
65
|
+
iconDay=int(data["iconDay"]),
|
|
66
|
+
iconDayV2=int(data["iconDayV2"]),
|
|
67
|
+
temperatureMax=float(data["temperatureMax"]),
|
|
68
|
+
temperatureMin=float(data["temperatureMin"]),
|
|
69
|
+
precipitation=float(data["precipitation"]),
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class Forecast(TypedDict):
|
|
74
|
+
plz: str
|
|
75
|
+
currentWeather: CurrentWeather
|
|
76
|
+
regionForecast: list[DayForecast]
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def Forecast_from_meteoswiss_data(data: dict[str, Any]):
|
|
80
|
+
return Forecast(
|
|
81
|
+
plz=data["plz"],
|
|
82
|
+
currentWeather=data["currentWeather"],
|
|
83
|
+
regionForecast=[
|
|
84
|
+
DayForecast_from_meteoswiss_data(x) for x in data["regionForecast"]
|
|
85
|
+
],
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class CurrentCondition(TypedDict):
|
|
90
|
+
station: str
|
|
91
|
+
date: int
|
|
92
|
+
tre200s0: float | None
|
|
93
|
+
rre150z0: float | None
|
|
94
|
+
sre000z0: float | None
|
|
95
|
+
gre000z0: float | None
|
|
96
|
+
ure200s0: float | None
|
|
97
|
+
tde200s0: float | None
|
|
98
|
+
dkl010z0: float | None
|
|
99
|
+
fu3010z0: float | None
|
|
100
|
+
fu3010z1: float | None
|
|
101
|
+
prestas0: float | None
|
|
102
|
+
pp0qffs0: float | None
|
|
103
|
+
pp0qnhs0: float | None
|
|
104
|
+
ppz850s0: float | None
|
|
105
|
+
ppz700s0: float | None
|
|
106
|
+
dv1towz0: float | None
|
|
107
|
+
fu3towz0: float | None
|
|
108
|
+
fu3towz1: float | None
|
|
109
|
+
ta1tows0: float | None
|
|
110
|
+
uretows0: float | None
|
|
111
|
+
tdetows0: float | None
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def CurrentCondition_from_meteoswiss_data(data: dict[str, Any]) -> CurrentCondition:
|
|
115
|
+
def floatornone(val: Any) -> float | None:
|
|
116
|
+
if val == "" or val == "-":
|
|
117
|
+
return None
|
|
118
|
+
return float(val)
|
|
119
|
+
|
|
120
|
+
return CurrentCondition(
|
|
121
|
+
station=data["Station/Location"],
|
|
122
|
+
date=int(data["Date"]),
|
|
123
|
+
tre200s0=floatornone(data["tre200s0"]),
|
|
124
|
+
rre150z0=floatornone(data["rre150z0"]),
|
|
125
|
+
sre000z0=floatornone(data["sre000z0"]),
|
|
126
|
+
gre000z0=floatornone(data["gre000z0"]),
|
|
127
|
+
ure200s0=floatornone(data["ure200s0"]),
|
|
128
|
+
tde200s0=floatornone(data["tde200s0"]),
|
|
129
|
+
dkl010z0=floatornone(data["dkl010z0"]),
|
|
130
|
+
fu3010z0=floatornone(data["fu3010z0"]),
|
|
131
|
+
fu3010z1=floatornone(data["fu3010z1"]),
|
|
132
|
+
prestas0=floatornone(data["prestas0"]),
|
|
133
|
+
pp0qffs0=floatornone(data["pp0qffs0"]),
|
|
134
|
+
pp0qnhs0=floatornone(data["pp0qnhs0"]),
|
|
135
|
+
ppz850s0=floatornone(data["ppz850s0"]),
|
|
136
|
+
ppz700s0=floatornone(data["ppz700s0"]),
|
|
137
|
+
dv1towz0=floatornone(data["dv1towz0"]),
|
|
138
|
+
fu3towz0=floatornone(data["fu3towz0"]),
|
|
139
|
+
fu3towz1=floatornone(data["fu3towz1"]),
|
|
140
|
+
ta1tows0=floatornone(data["ta1tows0"]),
|
|
141
|
+
uretows0=floatornone(data["uretows0"]),
|
|
142
|
+
tdetows0=floatornone(data["tdetows0"]),
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
class ClientResult(TypedDict):
|
|
147
|
+
name: str
|
|
148
|
+
forecast: list[Forecast]
|
|
149
|
+
condition: list[CurrentCondition]
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def ClientResult_from_meteoswiss_data(data: dict[str, Any]) -> ClientResult:
|
|
153
|
+
return ClientResult(
|
|
154
|
+
name=data["name"],
|
|
155
|
+
forecast=Forecast_from_meteoswiss_data(data["forecast"]),
|
|
156
|
+
condition=[CurrentCondition_from_meteoswiss_data(x) for x in data["condition"]],
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
|
|
38
160
|
class meteoSwissClient:
|
|
39
161
|
def __init__(self, displayName=None, postcode=None, station=None):
|
|
40
162
|
_LOGGER.debug("MS Client INIT")
|
|
@@ -58,17 +180,15 @@ class meteoSwissClient:
|
|
|
58
180
|
"condition": self._condition,
|
|
59
181
|
}
|
|
60
182
|
|
|
183
|
+
def get_typed_data(self) -> ClientResult:
|
|
184
|
+
data = self.get_data()
|
|
185
|
+
return ClientResult_from_meteoswiss_data(data)
|
|
186
|
+
|
|
61
187
|
def get_24hforecast(self):
|
|
62
188
|
_LOGGER.debug("Start update 24h forecast data")
|
|
63
189
|
s = requests.Session()
|
|
64
190
|
# Forcing headers to avoid 500 error when downloading file
|
|
65
|
-
s.headers.update(
|
|
66
|
-
{
|
|
67
|
-
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
|
|
68
|
-
"Accept-Encoding": "gzip, deflate, sdch",
|
|
69
|
-
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/1337 Safari/537.36",
|
|
70
|
-
}
|
|
71
|
-
)
|
|
191
|
+
s.headers.update(_HEADERS)
|
|
72
192
|
searchUrl = MS_SEARCH_URL.format(self._postCode)
|
|
73
193
|
_LOGGER.debug("Main URL : %s" % searchUrl)
|
|
74
194
|
tmpSearch = s.get(searchUrl, timeout=10)
|
|
@@ -101,13 +221,7 @@ class meteoSwissClient:
|
|
|
101
221
|
_LOGGER.debug("Start update forecast data")
|
|
102
222
|
s = requests.Session()
|
|
103
223
|
# Forcing headers to avoid 500 error when downloading file
|
|
104
|
-
s.headers.update(
|
|
105
|
-
{
|
|
106
|
-
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
|
|
107
|
-
"Accept-Encoding": "gzip, deflate, sdch",
|
|
108
|
-
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/1337 Safari/537.36",
|
|
109
|
-
}
|
|
110
|
-
)
|
|
224
|
+
s.headers.update(_HEADERS)
|
|
111
225
|
|
|
112
226
|
jsonUrl = JSON_FORECAST_URL.format(self._postCode)
|
|
113
227
|
jsonData = s.get(jsonUrl, timeout=10)
|
|
@@ -194,7 +308,7 @@ class meteoSwissClient:
|
|
|
194
308
|
data.sort(key=lambda tup: tup[0])
|
|
195
309
|
try:
|
|
196
310
|
return data[0][1]
|
|
197
|
-
except:
|
|
311
|
+
except BaseException:
|
|
198
312
|
_LOGGER.warning(
|
|
199
313
|
"Unable to get closest station for lat : %s lon : %s"
|
|
200
314
|
% (currentLat, currnetLon)
|
|
@@ -213,24 +327,22 @@ class meteoSwissClient:
|
|
|
213
327
|
|
|
214
328
|
def getGeoData(self, lat, lon):
|
|
215
329
|
s = requests.Session()
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
"Accept-Encoding": "gzip, deflate, sdch",
|
|
222
|
-
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/1337 Safari/537.36",
|
|
223
|
-
}
|
|
330
|
+
s.headers.update(_HEADERS)
|
|
331
|
+
|
|
332
|
+
uri = (
|
|
333
|
+
"https://nominatim.openstreetmap.org/reverse"
|
|
334
|
+
f"?format=jsonv2&lat={lat}&lon={lon}&zoom=18"
|
|
224
335
|
)
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
336
|
+
_LOGGER.debug("Requesting Nominatim OSM data at URL %s", uri)
|
|
337
|
+
geoData_req = s.get(uri)
|
|
338
|
+
try:
|
|
339
|
+
geoData_req.raise_for_status()
|
|
340
|
+
geoData = geoData_req.json
|
|
341
|
+
_LOGGER.debug("Got data from OpenStreetMap: %s" % (geoData))
|
|
342
|
+
return geoData
|
|
343
|
+
except Exception:
|
|
344
|
+
_LOGGER.exception("Cannot get Nominatim OSM data: %s", geoData_req.text)
|
|
345
|
+
raise
|
|
234
346
|
|
|
235
347
|
def getPostCode(self, lat, lon):
|
|
236
348
|
geoData = self.getGeoData(lat, lon)
|
|
File without changes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: hamsclientfork
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.9
|
|
4
4
|
Summary: Library to get data from meteo swiss
|
|
5
5
|
Home-page: https://github.com/Rudd-O/hamsclientfork
|
|
6
6
|
Author: websylv
|
|
@@ -15,6 +15,10 @@ Classifier: Programming Language :: Python :: 3.9
|
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.10
|
|
16
16
|
Classifier: Programming Language :: Python :: 3.11
|
|
17
17
|
License-File: LICENSE
|
|
18
|
+
Requires-Dist: requests>=2.22.0
|
|
19
|
+
Requires-Dist: pandas>=0.25.3
|
|
20
|
+
Requires-Dist: beautifulsoup4>=4.8.2
|
|
21
|
+
Requires-Dist: geopy>=2.0.0
|
|
18
22
|
|
|
19
23
|
meteoswiss
|
|
20
24
|
==========
|
|
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
|