meteo-lt-pkg 0.5.1__tar.gz → 0.5.3__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.
- {meteo_lt_pkg-0.5.1/meteo_lt_pkg.egg-info → meteo_lt_pkg-0.5.3}/PKG-INFO +109 -11
- {meteo_lt_pkg-0.5.1 → meteo_lt_pkg-0.5.3}/README.md +108 -10
- {meteo_lt_pkg-0.5.1 → meteo_lt_pkg-0.5.3}/meteo_lt/__init__.py +2 -2
- {meteo_lt_pkg-0.5.1 → meteo_lt_pkg-0.5.3}/meteo_lt/api.py +27 -13
- {meteo_lt_pkg-0.5.1 → meteo_lt_pkg-0.5.3}/meteo_lt/client.py +4 -4
- {meteo_lt_pkg-0.5.1 → meteo_lt_pkg-0.5.3}/meteo_lt/const.py +2 -1
- {meteo_lt_pkg-0.5.1 → meteo_lt_pkg-0.5.3}/meteo_lt/models.py +7 -5
- {meteo_lt_pkg-0.5.1 → meteo_lt_pkg-0.5.3}/meteo_lt/warnings.py +49 -31
- {meteo_lt_pkg-0.5.1 → meteo_lt_pkg-0.5.3/meteo_lt_pkg.egg-info}/PKG-INFO +109 -11
- {meteo_lt_pkg-0.5.1 → meteo_lt_pkg-0.5.3}/pyproject.toml +1 -1
- {meteo_lt_pkg-0.5.1 → meteo_lt_pkg-0.5.3}/LICENSE +0 -0
- {meteo_lt_pkg-0.5.1 → meteo_lt_pkg-0.5.3}/MANIFEST.in +0 -0
- {meteo_lt_pkg-0.5.1 → meteo_lt_pkg-0.5.3}/meteo_lt/utils.py +0 -0
- {meteo_lt_pkg-0.5.1 → meteo_lt_pkg-0.5.3}/meteo_lt_pkg.egg-info/SOURCES.txt +0 -0
- {meteo_lt_pkg-0.5.1 → meteo_lt_pkg-0.5.3}/meteo_lt_pkg.egg-info/dependency_links.txt +0 -0
- {meteo_lt_pkg-0.5.1 → meteo_lt_pkg-0.5.3}/meteo_lt_pkg.egg-info/requires.txt +0 -0
- {meteo_lt_pkg-0.5.1 → meteo_lt_pkg-0.5.3}/meteo_lt_pkg.egg-info/top_level.txt +0 -0
- {meteo_lt_pkg-0.5.1 → meteo_lt_pkg-0.5.3}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: meteo_lt-pkg
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.3
|
|
4
4
|
Summary: A library to fetch weather data from api.meteo.lt
|
|
5
5
|
Author-email: Brunas <brunonas@gmail.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/Brunas/meteo_lt-pkg
|
|
@@ -212,6 +212,8 @@ async def fetch_warnings():
|
|
|
212
212
|
print(f"Warning: {warning.warning_type} in {warning.county}")
|
|
213
213
|
print(f"Severity: {warning.severity}")
|
|
214
214
|
print(f"Description: {warning.description}")
|
|
215
|
+
if warning.instruction:
|
|
216
|
+
print(f"Instruction: {warning.instruction}")
|
|
215
217
|
print(f"Active: {warning.start_time} to {warning.end_time}")
|
|
216
218
|
print("-" * 50)
|
|
217
219
|
|
|
@@ -228,6 +230,70 @@ asyncio.run(fetch_warnings())
|
|
|
228
230
|
asyncio.run(fetch_warnings_for_area())
|
|
229
231
|
```
|
|
230
232
|
|
|
233
|
+
### Fetching Hydrological Warnings
|
|
234
|
+
|
|
235
|
+
To get hydrological warnings (water-related warnings like floods, high water levels):
|
|
236
|
+
|
|
237
|
+
```python
|
|
238
|
+
async def fetch_hydro_warnings():
|
|
239
|
+
async with MeteoLtAPI() as api:
|
|
240
|
+
# Get all hydrological warnings
|
|
241
|
+
hydro_warnings = await api.get_hydro_warnings()
|
|
242
|
+
print(f"Total active hydro warnings: {len(hydro_warnings)}")
|
|
243
|
+
|
|
244
|
+
for warning in hydro_warnings:
|
|
245
|
+
print(f"Hydro Warning: {warning.warning_type} in {warning.county}")
|
|
246
|
+
print(f"Severity: {warning.severity}")
|
|
247
|
+
print(f"Description: {warning.description}")
|
|
248
|
+
if warning.instruction:
|
|
249
|
+
print(f"Instruction: {warning.instruction}")
|
|
250
|
+
print("-" * 50)
|
|
251
|
+
|
|
252
|
+
async def fetch_hydro_warnings_for_area():
|
|
253
|
+
async with MeteoLtAPI() as api:
|
|
254
|
+
# Get hydro warnings for specific administrative division
|
|
255
|
+
warnings = await api.get_hydro_warnings("Vilniaus miesto")
|
|
256
|
+
print(f"Hydro warnings for Vilnius: {len(warnings)}")
|
|
257
|
+
|
|
258
|
+
asyncio.run(fetch_hydro_warnings())
|
|
259
|
+
asyncio.run(fetch_hydro_warnings_for_area())
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### Fetching All Warnings (Weather + Hydrological)
|
|
263
|
+
|
|
264
|
+
To get both weather and hydrological warnings combined:
|
|
265
|
+
|
|
266
|
+
```python
|
|
267
|
+
async def fetch_all_warnings():
|
|
268
|
+
async with MeteoLtAPI() as api:
|
|
269
|
+
# Get all warnings (weather + hydrological)
|
|
270
|
+
all_warnings = await api.get_all_warnings()
|
|
271
|
+
print(f"Total active warnings (all types): {len(all_warnings)}")
|
|
272
|
+
|
|
273
|
+
for warning in all_warnings:
|
|
274
|
+
print(f"{warning.warning_type} in {warning.county}")
|
|
275
|
+
print(f"Severity: {warning.severity}")
|
|
276
|
+
print(f"Description: {warning.description}")
|
|
277
|
+
if warning.instruction:
|
|
278
|
+
print(f"Instruction: {warning.instruction}")
|
|
279
|
+
print("-" * 50)
|
|
280
|
+
|
|
281
|
+
async def fetch_all_warnings_for_area():
|
|
282
|
+
async with MeteoLtAPI() as api:
|
|
283
|
+
# Get all warnings for specific administrative division
|
|
284
|
+
warnings = await api.get_all_warnings("Vilniaus miesto")
|
|
285
|
+
print(f"All warnings for Vilnius: {len(warnings)}")
|
|
286
|
+
|
|
287
|
+
# Separate by type if needed
|
|
288
|
+
weather_count = sum(1 for w in warnings if w.category == "weather")
|
|
289
|
+
hydro_count = sum(1 for w in warnings if w.category == "hydro")
|
|
290
|
+
print(f" Weather warnings: {weather_count}")
|
|
291
|
+
print(f" Hydro warnings: {hydro_count}")
|
|
292
|
+
|
|
293
|
+
asyncio.run(fetch_all_warnings())
|
|
294
|
+
asyncio.run(fetch_all_warnings_for_area())
|
|
295
|
+
```
|
|
296
|
+
|
|
231
297
|
## Data Models
|
|
232
298
|
|
|
233
299
|
The package includes several data models to represent the API responses:
|
|
@@ -250,8 +316,15 @@ Represents a place with associated metadata.
|
|
|
250
316
|
```python
|
|
251
317
|
from meteo_lt import Place
|
|
252
318
|
|
|
253
|
-
place = Place(
|
|
319
|
+
place = Place(
|
|
320
|
+
code="vilnius",
|
|
321
|
+
name="Vilnius",
|
|
322
|
+
administrative_division="Vilniaus miesto",
|
|
323
|
+
country_code="LT",
|
|
324
|
+
coordinates=coords
|
|
325
|
+
)
|
|
254
326
|
print(place.latitude, place.longitude)
|
|
327
|
+
print(place.counties) # List of counties this place belongs to
|
|
255
328
|
```
|
|
256
329
|
|
|
257
330
|
### ForecastTimestamp
|
|
@@ -274,7 +347,10 @@ forecast_timestamp = ForecastTimestamp(
|
|
|
274
347
|
humidity=60,
|
|
275
348
|
precipitation=0
|
|
276
349
|
)
|
|
277
|
-
print(forecast_timestamp.
|
|
350
|
+
print(f"Temperature: {forecast_timestamp.temperature}°C")
|
|
351
|
+
print(f"Condition: {forecast_timestamp.condition_code}")
|
|
352
|
+
# Warnings list is automatically populated when using get_forecast_with_warnings()
|
|
353
|
+
print(f"Warnings: {len(forecast_timestamp.warnings)}")
|
|
278
354
|
```
|
|
279
355
|
|
|
280
356
|
### Forecast
|
|
@@ -286,28 +362,50 @@ from meteo_lt import Forecast
|
|
|
286
362
|
|
|
287
363
|
forecast = Forecast(
|
|
288
364
|
place=place,
|
|
289
|
-
forecast_created=
|
|
365
|
+
forecast_created="2024-07-23T12:00:00+00:00",
|
|
366
|
+
current_conditions=forecast_timestamp,
|
|
290
367
|
forecast_timestamps=[forecast_timestamp]
|
|
291
368
|
)
|
|
292
|
-
|
|
369
|
+
# current_conditions is automatically set to the current hour's forecast
|
|
370
|
+
print(f"Current temperature: {forecast.current_conditions.temperature}°C")
|
|
371
|
+
# forecast_timestamps are automatically filtered to exclude past hours
|
|
372
|
+
print(f"Future forecasts: {len(forecast.forecast_timestamps)}")
|
|
293
373
|
```
|
|
294
374
|
|
|
295
|
-
###
|
|
375
|
+
### MeteoWarning
|
|
296
376
|
|
|
297
|
-
Represents a
|
|
377
|
+
Represents a meteorological warning (weather or hydrological) for a specific area.
|
|
298
378
|
|
|
299
379
|
```python
|
|
300
|
-
from meteo_lt import
|
|
380
|
+
from meteo_lt import MeteoWarning
|
|
301
381
|
|
|
302
|
-
warning
|
|
382
|
+
# Weather warning example
|
|
383
|
+
weather_warning = MeteoWarning(
|
|
303
384
|
county="Vilniaus apskritis",
|
|
304
385
|
warning_type="frost",
|
|
305
386
|
severity="Moderate",
|
|
306
387
|
description="Ground surface frost 0-5 degrees in many places",
|
|
388
|
+
instruction="Protect sensitive plants and be cautious on roads", # Optional safety instruction
|
|
389
|
+
category="weather",
|
|
307
390
|
start_time="2024-07-23T12:00:00Z",
|
|
308
391
|
end_time="2024-07-23T18:00:00Z"
|
|
309
392
|
)
|
|
310
|
-
print(f"Warning for {
|
|
393
|
+
print(f"Warning for {weather_warning.county}: {weather_warning.description}")
|
|
394
|
+
if weather_warning.instruction:
|
|
395
|
+
print(f"Safety instruction: {weather_warning.instruction}")
|
|
396
|
+
print(f"Category: {weather_warning.category}") # "weather" or "hydro"
|
|
397
|
+
|
|
398
|
+
# Hydrological warning example
|
|
399
|
+
hydro_warning = MeteoWarning(
|
|
400
|
+
county="Kauno apskritis",
|
|
401
|
+
warning_type="flood",
|
|
402
|
+
severity="High",
|
|
403
|
+
description="High water levels expected",
|
|
404
|
+
instruction="Avoid low-lying areas and do not attempt to cross flooded roads", # Optional
|
|
405
|
+
category="hydro",
|
|
406
|
+
start_time="2024-07-23T12:00:00Z",
|
|
407
|
+
end_time="2024-07-24T12:00:00Z"
|
|
408
|
+
)
|
|
311
409
|
```
|
|
312
410
|
|
|
313
411
|
### HydroStation
|
|
@@ -370,7 +468,7 @@ To get the list of all hydrological stations:
|
|
|
370
468
|
```python
|
|
371
469
|
async def fetch_hydro_stations():
|
|
372
470
|
async with MeteoLtAPI() as api:
|
|
373
|
-
stations = await api.
|
|
471
|
+
stations = await api.fetch_hydro_stations()
|
|
374
472
|
for station in stations:
|
|
375
473
|
print(f"{station.name} ({station.code}) - Water body: {station.water_body}")
|
|
376
474
|
|
|
@@ -185,6 +185,8 @@ async def fetch_warnings():
|
|
|
185
185
|
print(f"Warning: {warning.warning_type} in {warning.county}")
|
|
186
186
|
print(f"Severity: {warning.severity}")
|
|
187
187
|
print(f"Description: {warning.description}")
|
|
188
|
+
if warning.instruction:
|
|
189
|
+
print(f"Instruction: {warning.instruction}")
|
|
188
190
|
print(f"Active: {warning.start_time} to {warning.end_time}")
|
|
189
191
|
print("-" * 50)
|
|
190
192
|
|
|
@@ -201,6 +203,70 @@ asyncio.run(fetch_warnings())
|
|
|
201
203
|
asyncio.run(fetch_warnings_for_area())
|
|
202
204
|
```
|
|
203
205
|
|
|
206
|
+
### Fetching Hydrological Warnings
|
|
207
|
+
|
|
208
|
+
To get hydrological warnings (water-related warnings like floods, high water levels):
|
|
209
|
+
|
|
210
|
+
```python
|
|
211
|
+
async def fetch_hydro_warnings():
|
|
212
|
+
async with MeteoLtAPI() as api:
|
|
213
|
+
# Get all hydrological warnings
|
|
214
|
+
hydro_warnings = await api.get_hydro_warnings()
|
|
215
|
+
print(f"Total active hydro warnings: {len(hydro_warnings)}")
|
|
216
|
+
|
|
217
|
+
for warning in hydro_warnings:
|
|
218
|
+
print(f"Hydro Warning: {warning.warning_type} in {warning.county}")
|
|
219
|
+
print(f"Severity: {warning.severity}")
|
|
220
|
+
print(f"Description: {warning.description}")
|
|
221
|
+
if warning.instruction:
|
|
222
|
+
print(f"Instruction: {warning.instruction}")
|
|
223
|
+
print("-" * 50)
|
|
224
|
+
|
|
225
|
+
async def fetch_hydro_warnings_for_area():
|
|
226
|
+
async with MeteoLtAPI() as api:
|
|
227
|
+
# Get hydro warnings for specific administrative division
|
|
228
|
+
warnings = await api.get_hydro_warnings("Vilniaus miesto")
|
|
229
|
+
print(f"Hydro warnings for Vilnius: {len(warnings)}")
|
|
230
|
+
|
|
231
|
+
asyncio.run(fetch_hydro_warnings())
|
|
232
|
+
asyncio.run(fetch_hydro_warnings_for_area())
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### Fetching All Warnings (Weather + Hydrological)
|
|
236
|
+
|
|
237
|
+
To get both weather and hydrological warnings combined:
|
|
238
|
+
|
|
239
|
+
```python
|
|
240
|
+
async def fetch_all_warnings():
|
|
241
|
+
async with MeteoLtAPI() as api:
|
|
242
|
+
# Get all warnings (weather + hydrological)
|
|
243
|
+
all_warnings = await api.get_all_warnings()
|
|
244
|
+
print(f"Total active warnings (all types): {len(all_warnings)}")
|
|
245
|
+
|
|
246
|
+
for warning in all_warnings:
|
|
247
|
+
print(f"{warning.warning_type} in {warning.county}")
|
|
248
|
+
print(f"Severity: {warning.severity}")
|
|
249
|
+
print(f"Description: {warning.description}")
|
|
250
|
+
if warning.instruction:
|
|
251
|
+
print(f"Instruction: {warning.instruction}")
|
|
252
|
+
print("-" * 50)
|
|
253
|
+
|
|
254
|
+
async def fetch_all_warnings_for_area():
|
|
255
|
+
async with MeteoLtAPI() as api:
|
|
256
|
+
# Get all warnings for specific administrative division
|
|
257
|
+
warnings = await api.get_all_warnings("Vilniaus miesto")
|
|
258
|
+
print(f"All warnings for Vilnius: {len(warnings)}")
|
|
259
|
+
|
|
260
|
+
# Separate by type if needed
|
|
261
|
+
weather_count = sum(1 for w in warnings if w.category == "weather")
|
|
262
|
+
hydro_count = sum(1 for w in warnings if w.category == "hydro")
|
|
263
|
+
print(f" Weather warnings: {weather_count}")
|
|
264
|
+
print(f" Hydro warnings: {hydro_count}")
|
|
265
|
+
|
|
266
|
+
asyncio.run(fetch_all_warnings())
|
|
267
|
+
asyncio.run(fetch_all_warnings_for_area())
|
|
268
|
+
```
|
|
269
|
+
|
|
204
270
|
## Data Models
|
|
205
271
|
|
|
206
272
|
The package includes several data models to represent the API responses:
|
|
@@ -223,8 +289,15 @@ Represents a place with associated metadata.
|
|
|
223
289
|
```python
|
|
224
290
|
from meteo_lt import Place
|
|
225
291
|
|
|
226
|
-
place = Place(
|
|
292
|
+
place = Place(
|
|
293
|
+
code="vilnius",
|
|
294
|
+
name="Vilnius",
|
|
295
|
+
administrative_division="Vilniaus miesto",
|
|
296
|
+
country_code="LT",
|
|
297
|
+
coordinates=coords
|
|
298
|
+
)
|
|
227
299
|
print(place.latitude, place.longitude)
|
|
300
|
+
print(place.counties) # List of counties this place belongs to
|
|
228
301
|
```
|
|
229
302
|
|
|
230
303
|
### ForecastTimestamp
|
|
@@ -247,7 +320,10 @@ forecast_timestamp = ForecastTimestamp(
|
|
|
247
320
|
humidity=60,
|
|
248
321
|
precipitation=0
|
|
249
322
|
)
|
|
250
|
-
print(forecast_timestamp.
|
|
323
|
+
print(f"Temperature: {forecast_timestamp.temperature}°C")
|
|
324
|
+
print(f"Condition: {forecast_timestamp.condition_code}")
|
|
325
|
+
# Warnings list is automatically populated when using get_forecast_with_warnings()
|
|
326
|
+
print(f"Warnings: {len(forecast_timestamp.warnings)}")
|
|
251
327
|
```
|
|
252
328
|
|
|
253
329
|
### Forecast
|
|
@@ -259,28 +335,50 @@ from meteo_lt import Forecast
|
|
|
259
335
|
|
|
260
336
|
forecast = Forecast(
|
|
261
337
|
place=place,
|
|
262
|
-
forecast_created=
|
|
338
|
+
forecast_created="2024-07-23T12:00:00+00:00",
|
|
339
|
+
current_conditions=forecast_timestamp,
|
|
263
340
|
forecast_timestamps=[forecast_timestamp]
|
|
264
341
|
)
|
|
265
|
-
|
|
342
|
+
# current_conditions is automatically set to the current hour's forecast
|
|
343
|
+
print(f"Current temperature: {forecast.current_conditions.temperature}°C")
|
|
344
|
+
# forecast_timestamps are automatically filtered to exclude past hours
|
|
345
|
+
print(f"Future forecasts: {len(forecast.forecast_timestamps)}")
|
|
266
346
|
```
|
|
267
347
|
|
|
268
|
-
###
|
|
348
|
+
### MeteoWarning
|
|
269
349
|
|
|
270
|
-
Represents a
|
|
350
|
+
Represents a meteorological warning (weather or hydrological) for a specific area.
|
|
271
351
|
|
|
272
352
|
```python
|
|
273
|
-
from meteo_lt import
|
|
353
|
+
from meteo_lt import MeteoWarning
|
|
274
354
|
|
|
275
|
-
warning
|
|
355
|
+
# Weather warning example
|
|
356
|
+
weather_warning = MeteoWarning(
|
|
276
357
|
county="Vilniaus apskritis",
|
|
277
358
|
warning_type="frost",
|
|
278
359
|
severity="Moderate",
|
|
279
360
|
description="Ground surface frost 0-5 degrees in many places",
|
|
361
|
+
instruction="Protect sensitive plants and be cautious on roads", # Optional safety instruction
|
|
362
|
+
category="weather",
|
|
280
363
|
start_time="2024-07-23T12:00:00Z",
|
|
281
364
|
end_time="2024-07-23T18:00:00Z"
|
|
282
365
|
)
|
|
283
|
-
print(f"Warning for {
|
|
366
|
+
print(f"Warning for {weather_warning.county}: {weather_warning.description}")
|
|
367
|
+
if weather_warning.instruction:
|
|
368
|
+
print(f"Safety instruction: {weather_warning.instruction}")
|
|
369
|
+
print(f"Category: {weather_warning.category}") # "weather" or "hydro"
|
|
370
|
+
|
|
371
|
+
# Hydrological warning example
|
|
372
|
+
hydro_warning = MeteoWarning(
|
|
373
|
+
county="Kauno apskritis",
|
|
374
|
+
warning_type="flood",
|
|
375
|
+
severity="High",
|
|
376
|
+
description="High water levels expected",
|
|
377
|
+
instruction="Avoid low-lying areas and do not attempt to cross flooded roads", # Optional
|
|
378
|
+
category="hydro",
|
|
379
|
+
start_time="2024-07-23T12:00:00Z",
|
|
380
|
+
end_time="2024-07-24T12:00:00Z"
|
|
381
|
+
)
|
|
284
382
|
```
|
|
285
383
|
|
|
286
384
|
### HydroStation
|
|
@@ -343,7 +441,7 @@ To get the list of all hydrological stations:
|
|
|
343
441
|
```python
|
|
344
442
|
async def fetch_hydro_stations():
|
|
345
443
|
async with MeteoLtAPI() as api:
|
|
346
|
-
stations = await api.
|
|
444
|
+
stations = await api.fetch_hydro_stations()
|
|
347
445
|
for station in stations:
|
|
348
446
|
print(f"{station.name} ({station.code}) - Water body: {station.water_body}")
|
|
349
447
|
|
|
@@ -7,7 +7,7 @@ from .models import (
|
|
|
7
7
|
Place,
|
|
8
8
|
ForecastTimestamp,
|
|
9
9
|
Forecast,
|
|
10
|
-
|
|
10
|
+
MeteoWarning,
|
|
11
11
|
HydroStation,
|
|
12
12
|
HydroObservation,
|
|
13
13
|
HydroObservationData,
|
|
@@ -20,7 +20,7 @@ __all__ = [
|
|
|
20
20
|
"Place",
|
|
21
21
|
"ForecastTimestamp",
|
|
22
22
|
"Forecast",
|
|
23
|
-
"
|
|
23
|
+
"MeteoWarning",
|
|
24
24
|
"HydroStation",
|
|
25
25
|
"HydroObservation",
|
|
26
26
|
"HydroObservationData",
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
"""Main API class script"""
|
|
2
2
|
|
|
3
|
+
import asyncio
|
|
3
4
|
from typing import List, Optional
|
|
4
5
|
|
|
5
6
|
from .models import (
|
|
6
7
|
Forecast,
|
|
7
8
|
Place,
|
|
8
|
-
|
|
9
|
+
MeteoWarning,
|
|
9
10
|
HydroStation,
|
|
10
11
|
HydroObservationData,
|
|
11
12
|
)
|
|
12
13
|
from .utils import find_nearest_location
|
|
13
14
|
from .client import MeteoLtClient
|
|
14
|
-
from .warnings import
|
|
15
|
+
from .warnings import WarningsProcessor
|
|
15
16
|
|
|
16
17
|
|
|
17
18
|
class MeteoLtAPI:
|
|
@@ -20,7 +21,8 @@ class MeteoLtAPI:
|
|
|
20
21
|
def __init__(self, session=None):
|
|
21
22
|
self.places = []
|
|
22
23
|
self.client = MeteoLtClient(session)
|
|
23
|
-
self.warnings_processor =
|
|
24
|
+
self.warnings_processor = WarningsProcessor(self.client, category="weather")
|
|
25
|
+
self.hydro_warnings_processor = WarningsProcessor(self.client, category="hydro")
|
|
24
26
|
|
|
25
27
|
async def __aenter__(self):
|
|
26
28
|
"""Async context manager entry"""
|
|
@@ -56,7 +58,7 @@ class MeteoLtAPI:
|
|
|
56
58
|
longitude: Optional[float] = None,
|
|
57
59
|
place_code: Optional[str] = None,
|
|
58
60
|
) -> Forecast:
|
|
59
|
-
"""Get forecast with
|
|
61
|
+
"""Get forecast with all warnings (weather and hydrological) for a location"""
|
|
60
62
|
if place_code is None:
|
|
61
63
|
if latitude is None or longitude is None:
|
|
62
64
|
raise ValueError("Either place_code or both latitude and longitude must be provided")
|
|
@@ -65,7 +67,7 @@ class MeteoLtAPI:
|
|
|
65
67
|
|
|
66
68
|
return await self.get_forecast(place_code, include_warnings=True)
|
|
67
69
|
|
|
68
|
-
async def get_forecast(self, place_code: str, include_warnings: bool =
|
|
70
|
+
async def get_forecast(self, place_code: str, include_warnings: bool = False) -> Forecast:
|
|
69
71
|
"""Retrieves forecast data from API"""
|
|
70
72
|
forecast = await self.client.fetch_forecast(place_code)
|
|
71
73
|
|
|
@@ -74,27 +76,39 @@ class MeteoLtAPI:
|
|
|
74
76
|
|
|
75
77
|
return forecast
|
|
76
78
|
|
|
77
|
-
async def get_weather_warnings(self, administrative_division: str = None) -> List[
|
|
79
|
+
async def get_weather_warnings(self, administrative_division: str = None) -> List[MeteoWarning]:
|
|
78
80
|
"""Fetches weather warnings from meteo.lt JSON API"""
|
|
79
|
-
return await self.warnings_processor.
|
|
81
|
+
return await self.warnings_processor.get_warnings(administrative_division)
|
|
82
|
+
|
|
83
|
+
async def get_hydro_warnings(self, administrative_division: str = None) -> List[MeteoWarning]:
|
|
84
|
+
"""Fetches hydrological warnings from meteo.lt JSON API"""
|
|
85
|
+
return await self.hydro_warnings_processor.get_warnings(administrative_division)
|
|
86
|
+
|
|
87
|
+
async def get_all_warnings(self, administrative_division: str = None) -> List[MeteoWarning]:
|
|
88
|
+
"""Fetches both weather and hydrological warnings from meteo.lt JSON API"""
|
|
89
|
+
weather_task = self.warnings_processor.get_warnings(administrative_division)
|
|
90
|
+
hydro_task = self.hydro_warnings_processor.get_warnings(administrative_division)
|
|
91
|
+
weather_warnings, hydro_warnings = await asyncio.gather(weather_task, hydro_task)
|
|
92
|
+
return weather_warnings + hydro_warnings
|
|
80
93
|
|
|
81
94
|
async def _enrich_forecast_with_warnings(self, forecast: Forecast) -> None:
|
|
82
|
-
"""Enrich forecast timestamps with relevant weather
|
|
95
|
+
"""Enrich forecast timestamps with all relevant warnings (weather and hydrological)"""
|
|
83
96
|
if not forecast or not forecast.place or not forecast.place.administrative_division:
|
|
84
97
|
return
|
|
85
98
|
|
|
86
|
-
|
|
99
|
+
all_warnings = await self.get_all_warnings(forecast.place.administrative_division)
|
|
87
100
|
|
|
88
|
-
if
|
|
89
|
-
|
|
101
|
+
if all_warnings:
|
|
102
|
+
# Use weather processor to enrich (logic is the same for both)
|
|
103
|
+
self.warnings_processor.enrich_forecast_with_warnings(forecast, all_warnings)
|
|
90
104
|
|
|
91
|
-
async def
|
|
105
|
+
async def fetch_hydro_stations(self) -> List[HydroStation]:
|
|
92
106
|
"""Get list of all hydrological stations"""
|
|
93
107
|
return await self.client.fetch_hydro_stations()
|
|
94
108
|
|
|
95
109
|
async def get_nearest_hydro_station(self, latitude: float, longitude: float) -> Optional[HydroStation]:
|
|
96
110
|
"""Find the nearest hydrological station to given coordinates"""
|
|
97
|
-
stations = await self.
|
|
111
|
+
stations = await self.fetch_hydro_stations()
|
|
98
112
|
if not stations:
|
|
99
113
|
return None
|
|
100
114
|
return find_nearest_location(latitude, longitude, stations)
|
|
@@ -12,7 +12,7 @@ from .models import (
|
|
|
12
12
|
HydroObservationData,
|
|
13
13
|
HydroObservation,
|
|
14
14
|
)
|
|
15
|
-
from .const import BASE_URL,
|
|
15
|
+
from .const import BASE_URL, TIMEOUT, ENCODING
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
class MeteoLtClient:
|
|
@@ -71,12 +71,12 @@ class MeteoLtClient:
|
|
|
71
71
|
response_json = await response.json()
|
|
72
72
|
return Forecast.from_dict(response_json)
|
|
73
73
|
|
|
74
|
-
async def
|
|
75
|
-
"""Fetches raw
|
|
74
|
+
async def fetch_warnings(self, warnings_url: str) -> Dict[str, Any]:
|
|
75
|
+
"""Fetches raw warnings data from meteo.lt JSON API"""
|
|
76
76
|
session = await self._get_session()
|
|
77
77
|
|
|
78
78
|
# Get the latest warnings file
|
|
79
|
-
async with session.get(
|
|
79
|
+
async with session.get(warnings_url) as response:
|
|
80
80
|
file_list = await response.json()
|
|
81
81
|
|
|
82
82
|
if not file_list:
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"""const.py"""
|
|
2
2
|
|
|
3
3
|
BASE_URL = "https://api.meteo.lt/v1"
|
|
4
|
-
WARNINGS_URL = "https://www.meteo.lt/app/mu-plugins/Meteo/Components/
|
|
4
|
+
WARNINGS_URL = "https://www.meteo.lt/app/mu-plugins/Meteo/Components/WeatherWarningsNew/list_JSON.php"
|
|
5
|
+
HYDRO_WARNINGS_URL = "https://www.meteo.lt/app/mu-plugins/Meteo/Components/HydroWarnings/list_JSON.php"
|
|
5
6
|
TIMEOUT = 30
|
|
6
7
|
ENCODING = "utf-8"
|
|
7
8
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from dataclasses import dataclass, field, fields
|
|
4
4
|
from datetime import datetime, timezone
|
|
5
|
-
from typing import
|
|
5
|
+
from typing import Any, Dict, List, Optional, Type
|
|
6
6
|
|
|
7
7
|
from .const import COUNTY_MUNICIPALITIES
|
|
8
8
|
|
|
@@ -50,15 +50,17 @@ class Place(LocationBase):
|
|
|
50
50
|
|
|
51
51
|
|
|
52
52
|
@dataclass
|
|
53
|
-
class
|
|
54
|
-
"""
|
|
53
|
+
class MeteoWarning:
|
|
54
|
+
"""Meteorological Warning (includes both weather and hydrological warnings)"""
|
|
55
55
|
|
|
56
56
|
county: str
|
|
57
57
|
warning_type: str
|
|
58
58
|
severity: str
|
|
59
59
|
description: str
|
|
60
|
+
category: str = "weather" # "weather" or "hydro"
|
|
60
61
|
start_time: Optional[str] = None
|
|
61
62
|
end_time: Optional[str] = None
|
|
63
|
+
instruction: Optional[str] = None
|
|
62
64
|
|
|
63
65
|
|
|
64
66
|
@dataclass
|
|
@@ -102,7 +104,7 @@ class ForecastTimestamp:
|
|
|
102
104
|
pressure: float = field(metadata={"json_key": "seaLevelPressure"})
|
|
103
105
|
humidity: float = field(metadata={"json_key": "relativeHumidity"})
|
|
104
106
|
precipitation: float = field(metadata={"json_key": "totalPrecipitation"})
|
|
105
|
-
warnings: List[
|
|
107
|
+
warnings: List[MeteoWarning] = field(default_factory=list, init=False)
|
|
106
108
|
|
|
107
109
|
|
|
108
110
|
@dataclass
|
|
@@ -169,7 +171,7 @@ Coordinates.from_dict = classmethod(from_dict)
|
|
|
169
171
|
Place.from_dict = classmethod(from_dict)
|
|
170
172
|
ForecastTimestamp.from_dict = classmethod(from_dict)
|
|
171
173
|
Forecast.from_dict = classmethod(from_dict)
|
|
172
|
-
|
|
174
|
+
MeteoWarning.from_dict = classmethod(from_dict)
|
|
173
175
|
HydroStation.from_dict = classmethod(from_dict)
|
|
174
176
|
HydroObservation.from_dict = classmethod(from_dict)
|
|
175
177
|
HydroObservationData.from_dict = classmethod(from_dict)
|
|
@@ -1,23 +1,30 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""Unified warnings processor for handling weather and hydrological warning-related logic"""
|
|
2
2
|
|
|
3
3
|
import re
|
|
4
4
|
from datetime import datetime, timezone
|
|
5
|
-
from typing import
|
|
5
|
+
from typing import Any, Dict, List, Literal, Optional
|
|
6
6
|
|
|
7
|
-
from .models import Forecast, WeatherWarning
|
|
8
|
-
from .const import COUNTY_MUNICIPALITIES
|
|
9
7
|
from .client import MeteoLtClient
|
|
8
|
+
from .const import COUNTY_MUNICIPALITIES, HYDRO_WARNINGS_URL, WARNINGS_URL
|
|
9
|
+
from .models import Forecast, MeteoWarning
|
|
10
10
|
|
|
11
|
+
WarningCategory = Literal["weather", "hydro"]
|
|
11
12
|
|
|
12
|
-
class WeatherWarningsProcessor:
|
|
13
|
-
"""Processes weather warnings data and handles warning-related logic"""
|
|
14
13
|
|
|
15
|
-
|
|
14
|
+
class WarningsProcessor:
|
|
15
|
+
"""Processes weather and hydrological warnings data and handles warning-related logic"""
|
|
16
|
+
|
|
17
|
+
def __init__(self, client: MeteoLtClient, category: WarningCategory = "weather"):
|
|
16
18
|
self.client = client
|
|
19
|
+
self.category = category
|
|
20
|
+
|
|
21
|
+
async def get_warnings(self, administrative_division: str = None) -> List[MeteoWarning]:
|
|
22
|
+
"""Fetches and processes warnings (weather or hydro based on category)"""
|
|
23
|
+
# Determine URL based on category
|
|
24
|
+
warnings_url = HYDRO_WARNINGS_URL if self.category == "hydro" else WARNINGS_URL
|
|
17
25
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
warnings_data = await self.client.fetch_weather_warnings()
|
|
26
|
+
# Fetch warnings data
|
|
27
|
+
warnings_data = await self.client.fetch_warnings(warnings_url)
|
|
21
28
|
warnings = self._parse_warnings_data(warnings_data)
|
|
22
29
|
|
|
23
30
|
# Filter by administrative division if specified
|
|
@@ -26,8 +33,8 @@ class WeatherWarningsProcessor:
|
|
|
26
33
|
|
|
27
34
|
return warnings
|
|
28
35
|
|
|
29
|
-
def _parse_warnings_data(self, warnings_data: Optional[Dict[str, Any]]) -> List[
|
|
30
|
-
"""Parse raw warnings data into
|
|
36
|
+
def _parse_warnings_data(self, warnings_data: Optional[Dict[str, Any]]) -> List[MeteoWarning]:
|
|
37
|
+
"""Parse raw warnings data into MeteoWarning objects"""
|
|
31
38
|
warnings = []
|
|
32
39
|
|
|
33
40
|
# Handle empty response (list instead of dict)
|
|
@@ -36,8 +43,12 @@ class WeatherWarningsProcessor:
|
|
|
36
43
|
|
|
37
44
|
# Parse the warnings data
|
|
38
45
|
for phenomenon_group in warnings_data.get("phenomenon_groups", []):
|
|
39
|
-
|
|
40
|
-
|
|
46
|
+
phenomenon_category = phenomenon_group.get("phenomenon_category")
|
|
47
|
+
|
|
48
|
+
# Filter based on category
|
|
49
|
+
if self.category == "hydro" and phenomenon_category != "hydrological":
|
|
50
|
+
continue
|
|
51
|
+
if self.category == "weather" and phenomenon_category == "hydrological":
|
|
41
52
|
continue
|
|
42
53
|
|
|
43
54
|
for area_group in phenomenon_group.get("area_groups", []):
|
|
@@ -54,8 +65,8 @@ class WeatherWarningsProcessor:
|
|
|
54
65
|
|
|
55
66
|
return warnings
|
|
56
67
|
|
|
57
|
-
def _create_warning_from_alert(self, alert: Dict[str, Any], area: Dict[str, Any]) ->
|
|
58
|
-
"""Create a
|
|
68
|
+
def _create_warning_from_alert(self, alert: Dict[str, Any], area: Dict[str, Any]) -> MeteoWarning:
|
|
69
|
+
"""Create a MeteoWarning from alert data"""
|
|
59
70
|
county = area.get("name", "Unknown")
|
|
60
71
|
phenomenon = alert.get("phenomenon", "")
|
|
61
72
|
severity = alert.get("severity", "Minor")
|
|
@@ -66,22 +77,20 @@ class WeatherWarningsProcessor:
|
|
|
66
77
|
inst_dict = alert.get("instruction", {})
|
|
67
78
|
|
|
68
79
|
description = desc_dict.get("en") or desc_dict.get("lt", "")
|
|
69
|
-
instruction = inst_dict.get("en") or inst_dict.get("lt", "")
|
|
70
|
-
|
|
71
|
-
full_description = description
|
|
72
|
-
if instruction:
|
|
73
|
-
full_description += f"\n\nRecommendations: {instruction}"
|
|
80
|
+
instruction = inst_dict.get("en") or inst_dict.get("lt", "") or None
|
|
74
81
|
|
|
75
|
-
return
|
|
82
|
+
return MeteoWarning(
|
|
76
83
|
county=county,
|
|
77
84
|
warning_type=warning_type,
|
|
78
85
|
severity=severity,
|
|
79
|
-
description=
|
|
86
|
+
description=description,
|
|
87
|
+
category=self.category,
|
|
80
88
|
start_time=alert.get("t_from"),
|
|
81
89
|
end_time=alert.get("t_to"),
|
|
90
|
+
instruction=instruction,
|
|
82
91
|
)
|
|
83
92
|
|
|
84
|
-
def _warning_affects_area(self, warning:
|
|
93
|
+
def _warning_affects_area(self, warning: MeteoWarning, administrative_division: str) -> bool:
|
|
85
94
|
"""Check if warning affects specified administrative division"""
|
|
86
95
|
admin_lower = administrative_division.lower().replace(" savivaldybė", "").replace(" sav.", "")
|
|
87
96
|
|
|
@@ -99,22 +108,31 @@ class WeatherWarningsProcessor:
|
|
|
99
108
|
|
|
100
109
|
return False
|
|
101
110
|
|
|
102
|
-
def enrich_forecast_with_warnings(self, forecast: Forecast, warnings: List[
|
|
103
|
-
"""Enrich forecast timestamps with relevant
|
|
111
|
+
def enrich_forecast_with_warnings(self, forecast: Forecast, warnings: List[MeteoWarning]) -> None:
|
|
112
|
+
"""Enrich forecast timestamps with relevant warnings
|
|
113
|
+
|
|
114
|
+
All warnings (weather and hydro) are added to 'warnings' attribute
|
|
115
|
+
"""
|
|
104
116
|
if not warnings:
|
|
105
117
|
return
|
|
106
118
|
|
|
107
119
|
# For each forecast timestamp, find applicable warnings
|
|
108
120
|
for timestamp in forecast.forecast_timestamps:
|
|
109
|
-
|
|
121
|
+
# Initialize warnings list if it doesn't exist
|
|
122
|
+
if not hasattr(timestamp, "warnings"):
|
|
123
|
+
timestamp.warnings = []
|
|
124
|
+
# Get warnings for this timestamp and extend the list
|
|
125
|
+
applicable_warnings = self._get_warnings_for_timestamp(timestamp.datetime, warnings)
|
|
126
|
+
timestamp.warnings.extend(applicable_warnings)
|
|
110
127
|
|
|
111
128
|
# Also add warnings to current conditions if available
|
|
112
129
|
if hasattr(forecast, "current_conditions") and forecast.current_conditions:
|
|
113
|
-
forecast.current_conditions
|
|
114
|
-
forecast.current_conditions.
|
|
115
|
-
)
|
|
130
|
+
if not hasattr(forecast.current_conditions, "warnings"):
|
|
131
|
+
forecast.current_conditions.warnings = []
|
|
132
|
+
applicable_warnings = self._get_warnings_for_timestamp(forecast.current_conditions.datetime, warnings)
|
|
133
|
+
forecast.current_conditions.warnings.extend(applicable_warnings)
|
|
116
134
|
|
|
117
|
-
def _get_warnings_for_timestamp(self, timestamp_str: str, warnings: List[
|
|
135
|
+
def _get_warnings_for_timestamp(self, timestamp_str: str, warnings: List[MeteoWarning]) -> List[MeteoWarning]:
|
|
118
136
|
"""Get warnings that are active for a specific timestamp"""
|
|
119
137
|
try:
|
|
120
138
|
timestamp = datetime.fromisoformat(timestamp_str).replace(tzinfo=timezone.utc)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: meteo_lt-pkg
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.3
|
|
4
4
|
Summary: A library to fetch weather data from api.meteo.lt
|
|
5
5
|
Author-email: Brunas <brunonas@gmail.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/Brunas/meteo_lt-pkg
|
|
@@ -212,6 +212,8 @@ async def fetch_warnings():
|
|
|
212
212
|
print(f"Warning: {warning.warning_type} in {warning.county}")
|
|
213
213
|
print(f"Severity: {warning.severity}")
|
|
214
214
|
print(f"Description: {warning.description}")
|
|
215
|
+
if warning.instruction:
|
|
216
|
+
print(f"Instruction: {warning.instruction}")
|
|
215
217
|
print(f"Active: {warning.start_time} to {warning.end_time}")
|
|
216
218
|
print("-" * 50)
|
|
217
219
|
|
|
@@ -228,6 +230,70 @@ asyncio.run(fetch_warnings())
|
|
|
228
230
|
asyncio.run(fetch_warnings_for_area())
|
|
229
231
|
```
|
|
230
232
|
|
|
233
|
+
### Fetching Hydrological Warnings
|
|
234
|
+
|
|
235
|
+
To get hydrological warnings (water-related warnings like floods, high water levels):
|
|
236
|
+
|
|
237
|
+
```python
|
|
238
|
+
async def fetch_hydro_warnings():
|
|
239
|
+
async with MeteoLtAPI() as api:
|
|
240
|
+
# Get all hydrological warnings
|
|
241
|
+
hydro_warnings = await api.get_hydro_warnings()
|
|
242
|
+
print(f"Total active hydro warnings: {len(hydro_warnings)}")
|
|
243
|
+
|
|
244
|
+
for warning in hydro_warnings:
|
|
245
|
+
print(f"Hydro Warning: {warning.warning_type} in {warning.county}")
|
|
246
|
+
print(f"Severity: {warning.severity}")
|
|
247
|
+
print(f"Description: {warning.description}")
|
|
248
|
+
if warning.instruction:
|
|
249
|
+
print(f"Instruction: {warning.instruction}")
|
|
250
|
+
print("-" * 50)
|
|
251
|
+
|
|
252
|
+
async def fetch_hydro_warnings_for_area():
|
|
253
|
+
async with MeteoLtAPI() as api:
|
|
254
|
+
# Get hydro warnings for specific administrative division
|
|
255
|
+
warnings = await api.get_hydro_warnings("Vilniaus miesto")
|
|
256
|
+
print(f"Hydro warnings for Vilnius: {len(warnings)}")
|
|
257
|
+
|
|
258
|
+
asyncio.run(fetch_hydro_warnings())
|
|
259
|
+
asyncio.run(fetch_hydro_warnings_for_area())
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### Fetching All Warnings (Weather + Hydrological)
|
|
263
|
+
|
|
264
|
+
To get both weather and hydrological warnings combined:
|
|
265
|
+
|
|
266
|
+
```python
|
|
267
|
+
async def fetch_all_warnings():
|
|
268
|
+
async with MeteoLtAPI() as api:
|
|
269
|
+
# Get all warnings (weather + hydrological)
|
|
270
|
+
all_warnings = await api.get_all_warnings()
|
|
271
|
+
print(f"Total active warnings (all types): {len(all_warnings)}")
|
|
272
|
+
|
|
273
|
+
for warning in all_warnings:
|
|
274
|
+
print(f"{warning.warning_type} in {warning.county}")
|
|
275
|
+
print(f"Severity: {warning.severity}")
|
|
276
|
+
print(f"Description: {warning.description}")
|
|
277
|
+
if warning.instruction:
|
|
278
|
+
print(f"Instruction: {warning.instruction}")
|
|
279
|
+
print("-" * 50)
|
|
280
|
+
|
|
281
|
+
async def fetch_all_warnings_for_area():
|
|
282
|
+
async with MeteoLtAPI() as api:
|
|
283
|
+
# Get all warnings for specific administrative division
|
|
284
|
+
warnings = await api.get_all_warnings("Vilniaus miesto")
|
|
285
|
+
print(f"All warnings for Vilnius: {len(warnings)}")
|
|
286
|
+
|
|
287
|
+
# Separate by type if needed
|
|
288
|
+
weather_count = sum(1 for w in warnings if w.category == "weather")
|
|
289
|
+
hydro_count = sum(1 for w in warnings if w.category == "hydro")
|
|
290
|
+
print(f" Weather warnings: {weather_count}")
|
|
291
|
+
print(f" Hydro warnings: {hydro_count}")
|
|
292
|
+
|
|
293
|
+
asyncio.run(fetch_all_warnings())
|
|
294
|
+
asyncio.run(fetch_all_warnings_for_area())
|
|
295
|
+
```
|
|
296
|
+
|
|
231
297
|
## Data Models
|
|
232
298
|
|
|
233
299
|
The package includes several data models to represent the API responses:
|
|
@@ -250,8 +316,15 @@ Represents a place with associated metadata.
|
|
|
250
316
|
```python
|
|
251
317
|
from meteo_lt import Place
|
|
252
318
|
|
|
253
|
-
place = Place(
|
|
319
|
+
place = Place(
|
|
320
|
+
code="vilnius",
|
|
321
|
+
name="Vilnius",
|
|
322
|
+
administrative_division="Vilniaus miesto",
|
|
323
|
+
country_code="LT",
|
|
324
|
+
coordinates=coords
|
|
325
|
+
)
|
|
254
326
|
print(place.latitude, place.longitude)
|
|
327
|
+
print(place.counties) # List of counties this place belongs to
|
|
255
328
|
```
|
|
256
329
|
|
|
257
330
|
### ForecastTimestamp
|
|
@@ -274,7 +347,10 @@ forecast_timestamp = ForecastTimestamp(
|
|
|
274
347
|
humidity=60,
|
|
275
348
|
precipitation=0
|
|
276
349
|
)
|
|
277
|
-
print(forecast_timestamp.
|
|
350
|
+
print(f"Temperature: {forecast_timestamp.temperature}°C")
|
|
351
|
+
print(f"Condition: {forecast_timestamp.condition_code}")
|
|
352
|
+
# Warnings list is automatically populated when using get_forecast_with_warnings()
|
|
353
|
+
print(f"Warnings: {len(forecast_timestamp.warnings)}")
|
|
278
354
|
```
|
|
279
355
|
|
|
280
356
|
### Forecast
|
|
@@ -286,28 +362,50 @@ from meteo_lt import Forecast
|
|
|
286
362
|
|
|
287
363
|
forecast = Forecast(
|
|
288
364
|
place=place,
|
|
289
|
-
forecast_created=
|
|
365
|
+
forecast_created="2024-07-23T12:00:00+00:00",
|
|
366
|
+
current_conditions=forecast_timestamp,
|
|
290
367
|
forecast_timestamps=[forecast_timestamp]
|
|
291
368
|
)
|
|
292
|
-
|
|
369
|
+
# current_conditions is automatically set to the current hour's forecast
|
|
370
|
+
print(f"Current temperature: {forecast.current_conditions.temperature}°C")
|
|
371
|
+
# forecast_timestamps are automatically filtered to exclude past hours
|
|
372
|
+
print(f"Future forecasts: {len(forecast.forecast_timestamps)}")
|
|
293
373
|
```
|
|
294
374
|
|
|
295
|
-
###
|
|
375
|
+
### MeteoWarning
|
|
296
376
|
|
|
297
|
-
Represents a
|
|
377
|
+
Represents a meteorological warning (weather or hydrological) for a specific area.
|
|
298
378
|
|
|
299
379
|
```python
|
|
300
|
-
from meteo_lt import
|
|
380
|
+
from meteo_lt import MeteoWarning
|
|
301
381
|
|
|
302
|
-
warning
|
|
382
|
+
# Weather warning example
|
|
383
|
+
weather_warning = MeteoWarning(
|
|
303
384
|
county="Vilniaus apskritis",
|
|
304
385
|
warning_type="frost",
|
|
305
386
|
severity="Moderate",
|
|
306
387
|
description="Ground surface frost 0-5 degrees in many places",
|
|
388
|
+
instruction="Protect sensitive plants and be cautious on roads", # Optional safety instruction
|
|
389
|
+
category="weather",
|
|
307
390
|
start_time="2024-07-23T12:00:00Z",
|
|
308
391
|
end_time="2024-07-23T18:00:00Z"
|
|
309
392
|
)
|
|
310
|
-
print(f"Warning for {
|
|
393
|
+
print(f"Warning for {weather_warning.county}: {weather_warning.description}")
|
|
394
|
+
if weather_warning.instruction:
|
|
395
|
+
print(f"Safety instruction: {weather_warning.instruction}")
|
|
396
|
+
print(f"Category: {weather_warning.category}") # "weather" or "hydro"
|
|
397
|
+
|
|
398
|
+
# Hydrological warning example
|
|
399
|
+
hydro_warning = MeteoWarning(
|
|
400
|
+
county="Kauno apskritis",
|
|
401
|
+
warning_type="flood",
|
|
402
|
+
severity="High",
|
|
403
|
+
description="High water levels expected",
|
|
404
|
+
instruction="Avoid low-lying areas and do not attempt to cross flooded roads", # Optional
|
|
405
|
+
category="hydro",
|
|
406
|
+
start_time="2024-07-23T12:00:00Z",
|
|
407
|
+
end_time="2024-07-24T12:00:00Z"
|
|
408
|
+
)
|
|
311
409
|
```
|
|
312
410
|
|
|
313
411
|
### HydroStation
|
|
@@ -370,7 +468,7 @@ To get the list of all hydrological stations:
|
|
|
370
468
|
```python
|
|
371
469
|
async def fetch_hydro_stations():
|
|
372
470
|
async with MeteoLtAPI() as api:
|
|
373
|
-
stations = await api.
|
|
471
|
+
stations = await api.fetch_hydro_stations()
|
|
374
472
|
for station in stations:
|
|
375
473
|
print(f"{station.name} ({station.code}) - Water body: {station.water_body}")
|
|
376
474
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|