meteo-lt-pkg 0.5.0b0__tar.gz → 0.5.2__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meteo_lt-pkg
3
- Version: 0.5.0b0
3
+ Version: 0.5.2
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
@@ -228,6 +228,66 @@ asyncio.run(fetch_warnings())
228
228
  asyncio.run(fetch_warnings_for_area())
229
229
  ```
230
230
 
231
+ ### Fetching Hydrological Warnings
232
+
233
+ To get hydrological warnings (water-related warnings like floods, high water levels):
234
+
235
+ ```python
236
+ async def fetch_hydro_warnings():
237
+ async with MeteoLtAPI() as api:
238
+ # Get all hydrological warnings
239
+ hydro_warnings = await api.get_hydro_warnings()
240
+ print(f"Total active hydro warnings: {len(hydro_warnings)}")
241
+
242
+ for warning in hydro_warnings:
243
+ print(f"Hydro Warning: {warning.warning_type} in {warning.county}")
244
+ print(f"Severity: {warning.severity}")
245
+ print(f"Description: {warning.description}")
246
+ print("-" * 50)
247
+
248
+ async def fetch_hydro_warnings_for_area():
249
+ async with MeteoLtAPI() as api:
250
+ # Get hydro warnings for specific administrative division
251
+ warnings = await api.get_hydro_warnings("Vilniaus miesto")
252
+ print(f"Hydro warnings for Vilnius: {len(warnings)}")
253
+
254
+ asyncio.run(fetch_hydro_warnings())
255
+ asyncio.run(fetch_hydro_warnings_for_area())
256
+ ```
257
+
258
+ ### Fetching All Warnings (Weather + Hydrological)
259
+
260
+ To get both weather and hydrological warnings combined:
261
+
262
+ ```python
263
+ async def fetch_all_warnings():
264
+ async with MeteoLtAPI() as api:
265
+ # Get all warnings (weather + hydrological)
266
+ all_warnings = await api.get_all_warnings()
267
+ print(f"Total active warnings (all types): {len(all_warnings)}")
268
+
269
+ for warning in all_warnings:
270
+ print(f"{warning.warning_type} in {warning.county}")
271
+ print(f"Severity: {warning.severity}")
272
+ print(f"Description: {warning.description}")
273
+ print("-" * 50)
274
+
275
+ async def fetch_all_warnings_for_area():
276
+ async with MeteoLtAPI() as api:
277
+ # Get all warnings for specific administrative division
278
+ warnings = await api.get_all_warnings("Vilniaus miesto")
279
+ print(f"All warnings for Vilnius: {len(warnings)}")
280
+
281
+ # Separate by type if needed
282
+ weather_count = sum(1 for w in warnings if w.category == "weather")
283
+ hydro_count = sum(1 for w in warnings if w.category == "hydro")
284
+ print(f" Weather warnings: {weather_count}")
285
+ print(f" Hydro warnings: {hydro_count}")
286
+
287
+ asyncio.run(fetch_all_warnings())
288
+ asyncio.run(fetch_all_warnings_for_area())
289
+ ```
290
+
231
291
  ## Data Models
232
292
 
233
293
  The package includes several data models to represent the API responses:
@@ -250,8 +310,15 @@ Represents a place with associated metadata.
250
310
  ```python
251
311
  from meteo_lt import Place
252
312
 
253
- place = Place(code="vilnius", name="Vilnius", administrative_division="Vilnius City Municipality", country="LT", coordinates=coords)
313
+ place = Place(
314
+ code="vilnius",
315
+ name="Vilnius",
316
+ administrative_division="Vilniaus miesto",
317
+ country_code="LT",
318
+ coordinates=coords
319
+ )
254
320
  print(place.latitude, place.longitude)
321
+ print(place.counties) # List of counties this place belongs to
255
322
  ```
256
323
 
257
324
  ### ForecastTimestamp
@@ -274,7 +341,10 @@ forecast_timestamp = ForecastTimestamp(
274
341
  humidity=60,
275
342
  precipitation=0
276
343
  )
277
- print(forecast_timestamp.condition)
344
+ print(f"Temperature: {forecast_timestamp.temperature}°C")
345
+ print(f"Condition: {forecast_timestamp.condition_code}")
346
+ # Warnings list is automatically populated when using get_forecast_with_warnings()
347
+ print(f"Warnings: {len(forecast_timestamp.warnings)}")
278
348
  ```
279
349
 
280
350
  ### Forecast
@@ -286,28 +356,176 @@ from meteo_lt import Forecast
286
356
 
287
357
  forecast = Forecast(
288
358
  place=place,
289
- forecast_created=datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
359
+ forecast_created="2024-07-23T12:00:00+00:00",
360
+ current_conditions=forecast_timestamp,
290
361
  forecast_timestamps=[forecast_timestamp]
291
362
  )
292
- print(forecast.current_conditions().temperature)
363
+ # current_conditions is automatically set to the current hour's forecast
364
+ print(f"Current temperature: {forecast.current_conditions.temperature}°C")
365
+ # forecast_timestamps are automatically filtered to exclude past hours
366
+ print(f"Future forecasts: {len(forecast.forecast_timestamps)}")
293
367
  ```
294
368
 
295
- ### WeatherWarning
369
+ ### MeteoWarning
296
370
 
297
- Represents a weather warning for a specific area.
371
+ Represents a meteorological warning (weather or hydrological) for a specific area.
298
372
 
299
373
  ```python
300
- from meteo_lt import WeatherWarning
374
+ from meteo_lt import MeteoWarning
301
375
 
302
- warning = WeatherWarning(
376
+ # Weather warning example
377
+ weather_warning = MeteoWarning(
303
378
  county="Vilniaus apskritis",
304
379
  warning_type="frost",
305
380
  severity="Moderate",
306
381
  description="Ground surface frost 0-5 degrees in many places",
382
+ category="weather",
307
383
  start_time="2024-07-23T12:00:00Z",
308
384
  end_time="2024-07-23T18:00:00Z"
309
385
  )
310
- print(f"Warning for {warning.county}: {warning.description}")
386
+ print(f"Warning for {weather_warning.county}: {weather_warning.description}")
387
+ print(f"Category: {weather_warning.category}") # "weather" or "hydro"
388
+
389
+ # Hydrological warning example
390
+ hydro_warning = MeteoWarning(
391
+ county="Kauno apskritis",
392
+ warning_type="flood",
393
+ severity="High",
394
+ description="High water levels expected",
395
+ category="hydro",
396
+ start_time="2024-07-23T12:00:00Z",
397
+ end_time="2024-07-24T12:00:00Z"
398
+ )
399
+ ```
400
+
401
+ ### HydroStation
402
+
403
+ Represents a hydrological observation station with water body information.
404
+
405
+ ```python
406
+ from meteo_lt import HydroStation
407
+
408
+ station = HydroStation(
409
+ code="klaipedos-juru-uosto-vms",
410
+ name="Klaipėdos jūrų uosto VMS",
411
+ water_body="Baltijos jūra",
412
+ coordinates=coords
413
+ )
414
+ print(f"Station: {station.name} on {station.water_body}")
415
+ ```
416
+
417
+ ### HydroObservation
418
+
419
+ Represents a single hydrological observation with water measurements.
420
+
421
+ ```python
422
+ from meteo_lt import HydroObservation
423
+
424
+ observation = HydroObservation(
425
+ observation_datetime="2024-07-23T12:00:00+00:00",
426
+ water_level=481.8,
427
+ water_temperature=15.5,
428
+ water_discharge=100.0
429
+ )
430
+ print(f"Water level: {observation.water_level} cm")
431
+ print(f"Water temperature: {observation.water_temperature}°C")
432
+ ```
433
+
434
+ ### HydroObservationData
435
+
436
+ Represents a collection of hydrological observations for a specific station.
437
+
438
+ ```python
439
+ from meteo_lt import HydroObservationData
440
+
441
+ data = HydroObservationData(
442
+ station=station,
443
+ observations=[observation],
444
+ observations_data_range={"from": "2024-07-01", "to": "2024-07-23"}
445
+ )
446
+ print(f"Station: {data.station.name}")
447
+ print(f"Observations: {len(data.observations)}")
448
+ ```
449
+
450
+ ## Hydrological Data
451
+
452
+ The package provides access to hydrological data from Lithuanian water monitoring stations.
453
+
454
+ ### Fetching Hydrological Stations
455
+
456
+ To get the list of all hydrological stations:
457
+
458
+ ```python
459
+ async def fetch_hydro_stations():
460
+ async with MeteoLtAPI() as api:
461
+ stations = await api.fetch_hydro_stations()
462
+ for station in stations:
463
+ print(f"{station.name} ({station.code}) - Water body: {station.water_body}")
464
+
465
+ asyncio.run(fetch_hydro_stations())
466
+ ```
467
+
468
+ ### Finding the Nearest Hydrological Station
469
+
470
+ You can find the nearest hydrological station using coordinates:
471
+
472
+ ```python
473
+ async def find_nearest_hydro_station():
474
+ async with MeteoLtAPI() as api:
475
+ # Example coordinates for Klaipėda, Lithuania
476
+ nearest_station = await api.get_nearest_hydro_station(55.6872, 21.2797)
477
+ print(f"Nearest station: {nearest_station.name}")
478
+ print(f"Water body: {nearest_station.water_body}")
479
+ print(f"Distance: approximately {nearest_station.latitude}, {nearest_station.longitude}")
480
+
481
+ asyncio.run(find_nearest_hydro_station())
482
+ ```
483
+
484
+ ### Fetching Hydrological Observations
485
+
486
+ To get water level and temperature observations for a specific station:
487
+
488
+ ```python
489
+ async def fetch_hydro_observations():
490
+ async with MeteoLtAPI() as api:
491
+ # Get observations for a station
492
+ hydro_data = await api.get_hydro_observation_data("klaipedos-juru-uosto-vms")
493
+
494
+ print(f"Station: {hydro_data.station.name}")
495
+ print(f"Water body: {hydro_data.station.water_body}")
496
+ print(f"\nRecent observations:")
497
+
498
+ for observation in hydro_data.observations[:5]:
499
+ print(f" {observation.observation_datetime}")
500
+ print(f" Water level: {observation.water_level} cm")
501
+ print(f" Water temperature: {observation.water_temperature}°C")
502
+ if observation.water_discharge:
503
+ print(f" Water discharge: {observation.water_discharge} m³/s")
504
+
505
+ asyncio.run(fetch_hydro_observations())
506
+ ```
507
+
508
+ ### Getting Observations for Nearest Station
509
+
510
+ Combine location finding with observation fetching:
511
+
512
+ ```python
513
+ async def get_nearest_station_observations():
514
+ async with MeteoLtAPI() as api:
515
+ # Find nearest hydro station to coordinates
516
+ nearest_station = await api.get_nearest_hydro_station(55.6872, 21.2797)
517
+
518
+ # Get observations for the nearest station
519
+ hydro_data = await api.get_hydro_observation_data(nearest_station.code)
520
+
521
+ print(f"Latest observations from {hydro_data.station.name}:")
522
+ if hydro_data.observations:
523
+ latest = hydro_data.observations[0]
524
+ print(f" Time: {latest.observation_datetime}")
525
+ print(f" Water level: {latest.water_level} cm")
526
+ print(f" Temperature: {latest.water_temperature}°C")
527
+
528
+ asyncio.run(get_nearest_station_observations())
311
529
  ```
312
530
 
313
531
  ## Contributing
@@ -201,6 +201,66 @@ asyncio.run(fetch_warnings())
201
201
  asyncio.run(fetch_warnings_for_area())
202
202
  ```
203
203
 
204
+ ### Fetching Hydrological Warnings
205
+
206
+ To get hydrological warnings (water-related warnings like floods, high water levels):
207
+
208
+ ```python
209
+ async def fetch_hydro_warnings():
210
+ async with MeteoLtAPI() as api:
211
+ # Get all hydrological warnings
212
+ hydro_warnings = await api.get_hydro_warnings()
213
+ print(f"Total active hydro warnings: {len(hydro_warnings)}")
214
+
215
+ for warning in hydro_warnings:
216
+ print(f"Hydro Warning: {warning.warning_type} in {warning.county}")
217
+ print(f"Severity: {warning.severity}")
218
+ print(f"Description: {warning.description}")
219
+ print("-" * 50)
220
+
221
+ async def fetch_hydro_warnings_for_area():
222
+ async with MeteoLtAPI() as api:
223
+ # Get hydro warnings for specific administrative division
224
+ warnings = await api.get_hydro_warnings("Vilniaus miesto")
225
+ print(f"Hydro warnings for Vilnius: {len(warnings)}")
226
+
227
+ asyncio.run(fetch_hydro_warnings())
228
+ asyncio.run(fetch_hydro_warnings_for_area())
229
+ ```
230
+
231
+ ### Fetching All Warnings (Weather + Hydrological)
232
+
233
+ To get both weather and hydrological warnings combined:
234
+
235
+ ```python
236
+ async def fetch_all_warnings():
237
+ async with MeteoLtAPI() as api:
238
+ # Get all warnings (weather + hydrological)
239
+ all_warnings = await api.get_all_warnings()
240
+ print(f"Total active warnings (all types): {len(all_warnings)}")
241
+
242
+ for warning in all_warnings:
243
+ print(f"{warning.warning_type} in {warning.county}")
244
+ print(f"Severity: {warning.severity}")
245
+ print(f"Description: {warning.description}")
246
+ print("-" * 50)
247
+
248
+ async def fetch_all_warnings_for_area():
249
+ async with MeteoLtAPI() as api:
250
+ # Get all warnings for specific administrative division
251
+ warnings = await api.get_all_warnings("Vilniaus miesto")
252
+ print(f"All warnings for Vilnius: {len(warnings)}")
253
+
254
+ # Separate by type if needed
255
+ weather_count = sum(1 for w in warnings if w.category == "weather")
256
+ hydro_count = sum(1 for w in warnings if w.category == "hydro")
257
+ print(f" Weather warnings: {weather_count}")
258
+ print(f" Hydro warnings: {hydro_count}")
259
+
260
+ asyncio.run(fetch_all_warnings())
261
+ asyncio.run(fetch_all_warnings_for_area())
262
+ ```
263
+
204
264
  ## Data Models
205
265
 
206
266
  The package includes several data models to represent the API responses:
@@ -223,8 +283,15 @@ Represents a place with associated metadata.
223
283
  ```python
224
284
  from meteo_lt import Place
225
285
 
226
- place = Place(code="vilnius", name="Vilnius", administrative_division="Vilnius City Municipality", country="LT", coordinates=coords)
286
+ place = Place(
287
+ code="vilnius",
288
+ name="Vilnius",
289
+ administrative_division="Vilniaus miesto",
290
+ country_code="LT",
291
+ coordinates=coords
292
+ )
227
293
  print(place.latitude, place.longitude)
294
+ print(place.counties) # List of counties this place belongs to
228
295
  ```
229
296
 
230
297
  ### ForecastTimestamp
@@ -247,7 +314,10 @@ forecast_timestamp = ForecastTimestamp(
247
314
  humidity=60,
248
315
  precipitation=0
249
316
  )
250
- print(forecast_timestamp.condition)
317
+ print(f"Temperature: {forecast_timestamp.temperature}°C")
318
+ print(f"Condition: {forecast_timestamp.condition_code}")
319
+ # Warnings list is automatically populated when using get_forecast_with_warnings()
320
+ print(f"Warnings: {len(forecast_timestamp.warnings)}")
251
321
  ```
252
322
 
253
323
  ### Forecast
@@ -259,28 +329,176 @@ from meteo_lt import Forecast
259
329
 
260
330
  forecast = Forecast(
261
331
  place=place,
262
- forecast_created=datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
332
+ forecast_created="2024-07-23T12:00:00+00:00",
333
+ current_conditions=forecast_timestamp,
263
334
  forecast_timestamps=[forecast_timestamp]
264
335
  )
265
- print(forecast.current_conditions().temperature)
336
+ # current_conditions is automatically set to the current hour's forecast
337
+ print(f"Current temperature: {forecast.current_conditions.temperature}°C")
338
+ # forecast_timestamps are automatically filtered to exclude past hours
339
+ print(f"Future forecasts: {len(forecast.forecast_timestamps)}")
266
340
  ```
267
341
 
268
- ### WeatherWarning
342
+ ### MeteoWarning
269
343
 
270
- Represents a weather warning for a specific area.
344
+ Represents a meteorological warning (weather or hydrological) for a specific area.
271
345
 
272
346
  ```python
273
- from meteo_lt import WeatherWarning
347
+ from meteo_lt import MeteoWarning
274
348
 
275
- warning = WeatherWarning(
349
+ # Weather warning example
350
+ weather_warning = MeteoWarning(
276
351
  county="Vilniaus apskritis",
277
352
  warning_type="frost",
278
353
  severity="Moderate",
279
354
  description="Ground surface frost 0-5 degrees in many places",
355
+ category="weather",
280
356
  start_time="2024-07-23T12:00:00Z",
281
357
  end_time="2024-07-23T18:00:00Z"
282
358
  )
283
- print(f"Warning for {warning.county}: {warning.description}")
359
+ print(f"Warning for {weather_warning.county}: {weather_warning.description}")
360
+ print(f"Category: {weather_warning.category}") # "weather" or "hydro"
361
+
362
+ # Hydrological warning example
363
+ hydro_warning = MeteoWarning(
364
+ county="Kauno apskritis",
365
+ warning_type="flood",
366
+ severity="High",
367
+ description="High water levels expected",
368
+ category="hydro",
369
+ start_time="2024-07-23T12:00:00Z",
370
+ end_time="2024-07-24T12:00:00Z"
371
+ )
372
+ ```
373
+
374
+ ### HydroStation
375
+
376
+ Represents a hydrological observation station with water body information.
377
+
378
+ ```python
379
+ from meteo_lt import HydroStation
380
+
381
+ station = HydroStation(
382
+ code="klaipedos-juru-uosto-vms",
383
+ name="Klaipėdos jūrų uosto VMS",
384
+ water_body="Baltijos jūra",
385
+ coordinates=coords
386
+ )
387
+ print(f"Station: {station.name} on {station.water_body}")
388
+ ```
389
+
390
+ ### HydroObservation
391
+
392
+ Represents a single hydrological observation with water measurements.
393
+
394
+ ```python
395
+ from meteo_lt import HydroObservation
396
+
397
+ observation = HydroObservation(
398
+ observation_datetime="2024-07-23T12:00:00+00:00",
399
+ water_level=481.8,
400
+ water_temperature=15.5,
401
+ water_discharge=100.0
402
+ )
403
+ print(f"Water level: {observation.water_level} cm")
404
+ print(f"Water temperature: {observation.water_temperature}°C")
405
+ ```
406
+
407
+ ### HydroObservationData
408
+
409
+ Represents a collection of hydrological observations for a specific station.
410
+
411
+ ```python
412
+ from meteo_lt import HydroObservationData
413
+
414
+ data = HydroObservationData(
415
+ station=station,
416
+ observations=[observation],
417
+ observations_data_range={"from": "2024-07-01", "to": "2024-07-23"}
418
+ )
419
+ print(f"Station: {data.station.name}")
420
+ print(f"Observations: {len(data.observations)}")
421
+ ```
422
+
423
+ ## Hydrological Data
424
+
425
+ The package provides access to hydrological data from Lithuanian water monitoring stations.
426
+
427
+ ### Fetching Hydrological Stations
428
+
429
+ To get the list of all hydrological stations:
430
+
431
+ ```python
432
+ async def fetch_hydro_stations():
433
+ async with MeteoLtAPI() as api:
434
+ stations = await api.fetch_hydro_stations()
435
+ for station in stations:
436
+ print(f"{station.name} ({station.code}) - Water body: {station.water_body}")
437
+
438
+ asyncio.run(fetch_hydro_stations())
439
+ ```
440
+
441
+ ### Finding the Nearest Hydrological Station
442
+
443
+ You can find the nearest hydrological station using coordinates:
444
+
445
+ ```python
446
+ async def find_nearest_hydro_station():
447
+ async with MeteoLtAPI() as api:
448
+ # Example coordinates for Klaipėda, Lithuania
449
+ nearest_station = await api.get_nearest_hydro_station(55.6872, 21.2797)
450
+ print(f"Nearest station: {nearest_station.name}")
451
+ print(f"Water body: {nearest_station.water_body}")
452
+ print(f"Distance: approximately {nearest_station.latitude}, {nearest_station.longitude}")
453
+
454
+ asyncio.run(find_nearest_hydro_station())
455
+ ```
456
+
457
+ ### Fetching Hydrological Observations
458
+
459
+ To get water level and temperature observations for a specific station:
460
+
461
+ ```python
462
+ async def fetch_hydro_observations():
463
+ async with MeteoLtAPI() as api:
464
+ # Get observations for a station
465
+ hydro_data = await api.get_hydro_observation_data("klaipedos-juru-uosto-vms")
466
+
467
+ print(f"Station: {hydro_data.station.name}")
468
+ print(f"Water body: {hydro_data.station.water_body}")
469
+ print(f"\nRecent observations:")
470
+
471
+ for observation in hydro_data.observations[:5]:
472
+ print(f" {observation.observation_datetime}")
473
+ print(f" Water level: {observation.water_level} cm")
474
+ print(f" Water temperature: {observation.water_temperature}°C")
475
+ if observation.water_discharge:
476
+ print(f" Water discharge: {observation.water_discharge} m³/s")
477
+
478
+ asyncio.run(fetch_hydro_observations())
479
+ ```
480
+
481
+ ### Getting Observations for Nearest Station
482
+
483
+ Combine location finding with observation fetching:
484
+
485
+ ```python
486
+ async def get_nearest_station_observations():
487
+ async with MeteoLtAPI() as api:
488
+ # Find nearest hydro station to coordinates
489
+ nearest_station = await api.get_nearest_hydro_station(55.6872, 21.2797)
490
+
491
+ # Get observations for the nearest station
492
+ hydro_data = await api.get_hydro_observation_data(nearest_station.code)
493
+
494
+ print(f"Latest observations from {hydro_data.station.name}:")
495
+ if hydro_data.observations:
496
+ latest = hydro_data.observations[0]
497
+ print(f" Time: {latest.observation_datetime}")
498
+ print(f" Water level: {latest.water_level} cm")
499
+ print(f" Temperature: {latest.water_temperature}°C")
500
+
501
+ asyncio.run(get_nearest_station_observations())
284
502
  ```
285
503
 
286
504
  ## Contributing
@@ -7,7 +7,7 @@ from .models import (
7
7
  Place,
8
8
  ForecastTimestamp,
9
9
  Forecast,
10
- WeatherWarning,
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
- "WeatherWarning",
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
- WeatherWarning,
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 WeatherWarningsProcessor
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 = WeatherWarningsProcessor(self.client)
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 weather warnings for a location"""
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 = True) -> Forecast:
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[WeatherWarning]:
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.get_weather_warnings(administrative_division)
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 warnings"""
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
- warnings = await self.get_weather_warnings(forecast.place.administrative_division)
99
+ all_warnings = await self.get_all_warnings(forecast.place.administrative_division)
87
100
 
88
- if warnings:
89
- self.warnings_processor.enrich_forecast_with_warnings(forecast, warnings)
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 get_hydro_stations(self) -> List[HydroStation]:
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.get_hydro_stations()
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, WARNINGS_URL, TIMEOUT, ENCODING
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 fetch_weather_warnings(self) -> Dict[str, Any]:
75
- """Fetches raw weather warnings data from meteo.lt JSON API"""
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(WARNINGS_URL) as response:
79
+ async with session.get(warnings_url) as response:
80
80
  file_list = await response.json()
81
81
 
82
82
  if not file_list:
@@ -93,35 +93,23 @@ class MeteoLtClient:
93
93
  session = await self._get_session()
94
94
  async with session.get(f"{BASE_URL}/hydro-stations") as resp:
95
95
  if resp.status == 200:
96
+ resp.encoding = ENCODING
96
97
  response = await resp.json()
97
98
  stations = []
98
99
  for station_data in response:
99
- stations.append(
100
- HydroStation(
101
- code=station_data.get("code"),
102
- name=station_data.get("name"),
103
- water_body=station_data.get("waterBody"),
104
- coordinates=station_data.get("coordinates", {}),
105
- )
106
- )
100
+ stations.append(HydroStation.from_dict(station_data))
107
101
  return stations
108
- else:
109
- raise Exception(f"API returned status {resp.status}")
102
+ raise aiohttp.ClientError(f"API returned status {resp.status}")
110
103
 
111
104
  async def fetch_hydro_station(self, station_code: str) -> HydroStation:
112
105
  """Get information about a specific hydrological station."""
113
106
  session = await self._get_session()
114
107
  async with session.get(f"{BASE_URL}/hydro-stations/{station_code}") as resp:
115
108
  if resp.status == 200:
109
+ resp.encoding = ENCODING
116
110
  response = await resp.json()
117
- return HydroStation(
118
- code=response.get("code"),
119
- name=response.get("name"),
120
- water_body=response.get("waterBody"),
121
- coordinates=response.get("coordinates", {}),
122
- )
123
- else:
124
- raise Exception(f"API returned status {resp.status}")
111
+ return HydroStation.from_dict(response)
112
+ raise aiohttp.ClientError(f"API returned status {resp.status}")
125
113
 
126
114
  async def fetch_hydro_observation_data(
127
115
  self,
@@ -136,28 +124,15 @@ class MeteoLtClient:
136
124
  ) as resp:
137
125
  if resp.status == 200:
138
126
  response = await resp.json()
139
- station = HydroStation(
140
- code=response["station"].get("code"),
141
- name=response["station"].get("name"),
142
- water_body=response["station"].get("waterBody"),
143
- coordinates=response["station"].get("coordinates", {}),
144
- )
127
+ station = HydroStation.from_dict(response.get("station"))
145
128
 
146
129
  observations = []
147
130
  for obs_data in response.get("observations", []):
148
- observations.append(
149
- HydroObservation(
150
- observation_datetime=obs_data.get("observationTimeUtc"),
151
- water_level=obs_data.get("waterLevel"),
152
- water_temperature=obs_data.get("waterTemperature"),
153
- water_discharge=obs_data.get("waterDischarge"),
154
- )
155
- )
131
+ observations.append(HydroObservation.from_dict(obs_data))
156
132
 
157
133
  return HydroObservationData(
158
134
  station=station,
159
135
  observations_data_range=response.get("observationsDataRange"),
160
136
  observations=observations,
161
137
  )
162
- else:
163
- raise Exception(f"API returned status {resp.status}")
138
+ raise aiohttp.ClientError(f"API returned status {resp.status}")
@@ -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/" "WeatherWarningsNew/list_JSON.php"
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
 
@@ -50,13 +50,14 @@ class Place(LocationBase):
50
50
 
51
51
 
52
52
  @dataclass
53
- class WeatherWarning:
54
- """Weather Warning"""
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
62
63
 
@@ -65,17 +66,17 @@ class WeatherWarning:
65
66
  class HydroStation(LocationBase):
66
67
  """Hydrological station data."""
67
68
 
68
- water_body: str
69
+ water_body: str = field(metadata={"json_key": "waterBody"})
69
70
 
70
71
 
71
72
  @dataclass
72
73
  class HydroObservation:
73
74
  """Single hydrological observation."""
74
75
 
75
- observation_datetime: Optional[str] = None
76
- water_level: Optional[float] = None # cm
77
- water_temperature: Optional[float] = None # °C
78
- water_discharge: Optional[float] = None # m3/s
76
+ observation_datetime: Optional[str] = field(default=None, metadata={"json_key": "observationTimeUtc"})
77
+ water_level: Optional[float] = field(default=None, metadata={"json_key": "waterLevel"}) # cm
78
+ water_temperature: Optional[float] = field(default=None, metadata={"json_key": "waterTemperature"}) # °C
79
+ water_discharge: Optional[float] = field(default=None, metadata={"json_key": "waterDischarge"}) # m3/s
79
80
 
80
81
 
81
82
  @dataclass
@@ -83,7 +84,7 @@ class HydroObservationData:
83
84
  """Observation data response."""
84
85
 
85
86
  station: HydroStation
86
- observations_data_range: Optional[dict] = None
87
+ observations_data_range: Optional[dict] = field(default=None, metadata={"json_key": "observationsDataRange"})
87
88
  observations: List[HydroObservation] = field(default_factory=list)
88
89
 
89
90
 
@@ -102,7 +103,7 @@ class ForecastTimestamp:
102
103
  pressure: float = field(metadata={"json_key": "seaLevelPressure"})
103
104
  humidity: float = field(metadata={"json_key": "relativeHumidity"})
104
105
  precipitation: float = field(metadata={"json_key": "totalPrecipitation"})
105
- warnings: List[WeatherWarning] = field(default_factory=list, init=False)
106
+ warnings: List[MeteoWarning] = field(default_factory=list, init=False)
106
107
 
107
108
 
108
109
  @dataclass
@@ -169,7 +170,7 @@ Coordinates.from_dict = classmethod(from_dict)
169
170
  Place.from_dict = classmethod(from_dict)
170
171
  ForecastTimestamp.from_dict = classmethod(from_dict)
171
172
  Forecast.from_dict = classmethod(from_dict)
172
- WeatherWarning.from_dict = classmethod(from_dict)
173
+ MeteoWarning.from_dict = classmethod(from_dict)
173
174
  HydroStation.from_dict = classmethod(from_dict)
174
175
  HydroObservation.from_dict = classmethod(from_dict)
175
176
  HydroObservationData.from_dict = classmethod(from_dict)
@@ -1,9 +1,8 @@
1
1
  """utils.py"""
2
2
 
3
3
  from math import radians, sin, cos, sqrt, atan2
4
- from typing import TypeVar, List
5
-
6
- LocationT = TypeVar("LocationT") # Type variable for location objects with latitude/longitude
4
+ from typing import List
5
+ from meteo_lt.models import LocationBase
7
6
 
8
7
 
9
8
  def haversine(lat1: float, lon1: float, lat2: float, lon2: float) -> float:
@@ -20,7 +19,7 @@ def haversine(lat1: float, lon1: float, lat2: float, lon2: float) -> float:
20
19
  return r * c
21
20
 
22
21
 
23
- def find_nearest_location(latitude: float, longitude: float, locations: List[LocationT]) -> LocationT:
22
+ def find_nearest_location(latitude: float, longitude: float, locations: List[LocationBase]) -> LocationBase:
24
23
  """Find the nearest location from a list of locations based on the given latitude and longitude."""
25
24
  nearest_location = None
26
25
  min_distance = float("inf")
@@ -1,23 +1,30 @@
1
- """Weather warnings processor for handling warning-related logic"""
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 List, Optional, Dict, Any
5
+ from typing import List, Optional, Dict, Any, Literal
6
6
 
7
- from .models import Forecast, WeatherWarning
8
- from .const import COUNTY_MUNICIPALITIES
7
+ from .models import Forecast, MeteoWarning
8
+ from .const import COUNTY_MUNICIPALITIES, WARNINGS_URL, HYDRO_WARNINGS_URL
9
9
  from .client import MeteoLtClient
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
- def __init__(self, client: MeteoLtClient):
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
- async def get_weather_warnings(self, administrative_division: str = None) -> List[WeatherWarning]:
19
- """Fetches and processes weather warnings"""
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[WeatherWarning]:
30
- """Parse raw warnings data into WeatherWarning objects"""
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
- # Skip hydrological warnings if needed (they're usually for water levels)
40
- if phenomenon_group.get("phenomenon_category") == "hydrological":
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]) -> WeatherWarning:
58
- """Create a WeatherWarning from alert data"""
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")
@@ -72,16 +83,17 @@ class WeatherWarningsProcessor:
72
83
  if instruction:
73
84
  full_description += f"\n\nRecommendations: {instruction}"
74
85
 
75
- return WeatherWarning(
86
+ return MeteoWarning(
76
87
  county=county,
77
88
  warning_type=warning_type,
78
89
  severity=severity,
79
90
  description=full_description,
91
+ category=self.category,
80
92
  start_time=alert.get("t_from"),
81
93
  end_time=alert.get("t_to"),
82
94
  )
83
95
 
84
- def _warning_affects_area(self, warning: WeatherWarning, administrative_division: str) -> bool:
96
+ def _warning_affects_area(self, warning: MeteoWarning, administrative_division: str) -> bool:
85
97
  """Check if warning affects specified administrative division"""
86
98
  admin_lower = administrative_division.lower().replace(" savivaldybė", "").replace(" sav.", "")
87
99
 
@@ -99,22 +111,31 @@ class WeatherWarningsProcessor:
99
111
 
100
112
  return False
101
113
 
102
- def enrich_forecast_with_warnings(self, forecast: Forecast, warnings: List[WeatherWarning]) -> None:
103
- """Enrich forecast timestamps with relevant weather warnings"""
114
+ def enrich_forecast_with_warnings(self, forecast: Forecast, warnings: List[MeteoWarning]) -> None:
115
+ """Enrich forecast timestamps with relevant warnings
116
+
117
+ All warnings (weather and hydro) are added to 'warnings' attribute
118
+ """
104
119
  if not warnings:
105
120
  return
106
121
 
107
122
  # For each forecast timestamp, find applicable warnings
108
123
  for timestamp in forecast.forecast_timestamps:
109
- timestamp.warnings = self._get_warnings_for_timestamp(timestamp.datetime, warnings)
124
+ # Initialize warnings list if it doesn't exist
125
+ if not hasattr(timestamp, "warnings"):
126
+ timestamp.warnings = []
127
+ # Get warnings for this timestamp and extend the list
128
+ applicable_warnings = self._get_warnings_for_timestamp(timestamp.datetime, warnings)
129
+ timestamp.warnings.extend(applicable_warnings)
110
130
 
111
131
  # Also add warnings to current conditions if available
112
132
  if hasattr(forecast, "current_conditions") and forecast.current_conditions:
113
- forecast.current_conditions.warnings = self._get_warnings_for_timestamp(
114
- forecast.current_conditions.datetime, warnings
115
- )
133
+ if not hasattr(forecast.current_conditions, "warnings"):
134
+ forecast.current_conditions.warnings = []
135
+ applicable_warnings = self._get_warnings_for_timestamp(forecast.current_conditions.datetime, warnings)
136
+ forecast.current_conditions.warnings.extend(applicable_warnings)
116
137
 
117
- def _get_warnings_for_timestamp(self, timestamp_str: str, warnings: List[WeatherWarning]) -> List[WeatherWarning]:
138
+ def _get_warnings_for_timestamp(self, timestamp_str: str, warnings: List[MeteoWarning]) -> List[MeteoWarning]:
118
139
  """Get warnings that are active for a specific timestamp"""
119
140
  try:
120
141
  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.0b0
3
+ Version: 0.5.2
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
@@ -228,6 +228,66 @@ asyncio.run(fetch_warnings())
228
228
  asyncio.run(fetch_warnings_for_area())
229
229
  ```
230
230
 
231
+ ### Fetching Hydrological Warnings
232
+
233
+ To get hydrological warnings (water-related warnings like floods, high water levels):
234
+
235
+ ```python
236
+ async def fetch_hydro_warnings():
237
+ async with MeteoLtAPI() as api:
238
+ # Get all hydrological warnings
239
+ hydro_warnings = await api.get_hydro_warnings()
240
+ print(f"Total active hydro warnings: {len(hydro_warnings)}")
241
+
242
+ for warning in hydro_warnings:
243
+ print(f"Hydro Warning: {warning.warning_type} in {warning.county}")
244
+ print(f"Severity: {warning.severity}")
245
+ print(f"Description: {warning.description}")
246
+ print("-" * 50)
247
+
248
+ async def fetch_hydro_warnings_for_area():
249
+ async with MeteoLtAPI() as api:
250
+ # Get hydro warnings for specific administrative division
251
+ warnings = await api.get_hydro_warnings("Vilniaus miesto")
252
+ print(f"Hydro warnings for Vilnius: {len(warnings)}")
253
+
254
+ asyncio.run(fetch_hydro_warnings())
255
+ asyncio.run(fetch_hydro_warnings_for_area())
256
+ ```
257
+
258
+ ### Fetching All Warnings (Weather + Hydrological)
259
+
260
+ To get both weather and hydrological warnings combined:
261
+
262
+ ```python
263
+ async def fetch_all_warnings():
264
+ async with MeteoLtAPI() as api:
265
+ # Get all warnings (weather + hydrological)
266
+ all_warnings = await api.get_all_warnings()
267
+ print(f"Total active warnings (all types): {len(all_warnings)}")
268
+
269
+ for warning in all_warnings:
270
+ print(f"{warning.warning_type} in {warning.county}")
271
+ print(f"Severity: {warning.severity}")
272
+ print(f"Description: {warning.description}")
273
+ print("-" * 50)
274
+
275
+ async def fetch_all_warnings_for_area():
276
+ async with MeteoLtAPI() as api:
277
+ # Get all warnings for specific administrative division
278
+ warnings = await api.get_all_warnings("Vilniaus miesto")
279
+ print(f"All warnings for Vilnius: {len(warnings)}")
280
+
281
+ # Separate by type if needed
282
+ weather_count = sum(1 for w in warnings if w.category == "weather")
283
+ hydro_count = sum(1 for w in warnings if w.category == "hydro")
284
+ print(f" Weather warnings: {weather_count}")
285
+ print(f" Hydro warnings: {hydro_count}")
286
+
287
+ asyncio.run(fetch_all_warnings())
288
+ asyncio.run(fetch_all_warnings_for_area())
289
+ ```
290
+
231
291
  ## Data Models
232
292
 
233
293
  The package includes several data models to represent the API responses:
@@ -250,8 +310,15 @@ Represents a place with associated metadata.
250
310
  ```python
251
311
  from meteo_lt import Place
252
312
 
253
- place = Place(code="vilnius", name="Vilnius", administrative_division="Vilnius City Municipality", country="LT", coordinates=coords)
313
+ place = Place(
314
+ code="vilnius",
315
+ name="Vilnius",
316
+ administrative_division="Vilniaus miesto",
317
+ country_code="LT",
318
+ coordinates=coords
319
+ )
254
320
  print(place.latitude, place.longitude)
321
+ print(place.counties) # List of counties this place belongs to
255
322
  ```
256
323
 
257
324
  ### ForecastTimestamp
@@ -274,7 +341,10 @@ forecast_timestamp = ForecastTimestamp(
274
341
  humidity=60,
275
342
  precipitation=0
276
343
  )
277
- print(forecast_timestamp.condition)
344
+ print(f"Temperature: {forecast_timestamp.temperature}°C")
345
+ print(f"Condition: {forecast_timestamp.condition_code}")
346
+ # Warnings list is automatically populated when using get_forecast_with_warnings()
347
+ print(f"Warnings: {len(forecast_timestamp.warnings)}")
278
348
  ```
279
349
 
280
350
  ### Forecast
@@ -286,28 +356,176 @@ from meteo_lt import Forecast
286
356
 
287
357
  forecast = Forecast(
288
358
  place=place,
289
- forecast_created=datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
359
+ forecast_created="2024-07-23T12:00:00+00:00",
360
+ current_conditions=forecast_timestamp,
290
361
  forecast_timestamps=[forecast_timestamp]
291
362
  )
292
- print(forecast.current_conditions().temperature)
363
+ # current_conditions is automatically set to the current hour's forecast
364
+ print(f"Current temperature: {forecast.current_conditions.temperature}°C")
365
+ # forecast_timestamps are automatically filtered to exclude past hours
366
+ print(f"Future forecasts: {len(forecast.forecast_timestamps)}")
293
367
  ```
294
368
 
295
- ### WeatherWarning
369
+ ### MeteoWarning
296
370
 
297
- Represents a weather warning for a specific area.
371
+ Represents a meteorological warning (weather or hydrological) for a specific area.
298
372
 
299
373
  ```python
300
- from meteo_lt import WeatherWarning
374
+ from meteo_lt import MeteoWarning
301
375
 
302
- warning = WeatherWarning(
376
+ # Weather warning example
377
+ weather_warning = MeteoWarning(
303
378
  county="Vilniaus apskritis",
304
379
  warning_type="frost",
305
380
  severity="Moderate",
306
381
  description="Ground surface frost 0-5 degrees in many places",
382
+ category="weather",
307
383
  start_time="2024-07-23T12:00:00Z",
308
384
  end_time="2024-07-23T18:00:00Z"
309
385
  )
310
- print(f"Warning for {warning.county}: {warning.description}")
386
+ print(f"Warning for {weather_warning.county}: {weather_warning.description}")
387
+ print(f"Category: {weather_warning.category}") # "weather" or "hydro"
388
+
389
+ # Hydrological warning example
390
+ hydro_warning = MeteoWarning(
391
+ county="Kauno apskritis",
392
+ warning_type="flood",
393
+ severity="High",
394
+ description="High water levels expected",
395
+ category="hydro",
396
+ start_time="2024-07-23T12:00:00Z",
397
+ end_time="2024-07-24T12:00:00Z"
398
+ )
399
+ ```
400
+
401
+ ### HydroStation
402
+
403
+ Represents a hydrological observation station with water body information.
404
+
405
+ ```python
406
+ from meteo_lt import HydroStation
407
+
408
+ station = HydroStation(
409
+ code="klaipedos-juru-uosto-vms",
410
+ name="Klaipėdos jūrų uosto VMS",
411
+ water_body="Baltijos jūra",
412
+ coordinates=coords
413
+ )
414
+ print(f"Station: {station.name} on {station.water_body}")
415
+ ```
416
+
417
+ ### HydroObservation
418
+
419
+ Represents a single hydrological observation with water measurements.
420
+
421
+ ```python
422
+ from meteo_lt import HydroObservation
423
+
424
+ observation = HydroObservation(
425
+ observation_datetime="2024-07-23T12:00:00+00:00",
426
+ water_level=481.8,
427
+ water_temperature=15.5,
428
+ water_discharge=100.0
429
+ )
430
+ print(f"Water level: {observation.water_level} cm")
431
+ print(f"Water temperature: {observation.water_temperature}°C")
432
+ ```
433
+
434
+ ### HydroObservationData
435
+
436
+ Represents a collection of hydrological observations for a specific station.
437
+
438
+ ```python
439
+ from meteo_lt import HydroObservationData
440
+
441
+ data = HydroObservationData(
442
+ station=station,
443
+ observations=[observation],
444
+ observations_data_range={"from": "2024-07-01", "to": "2024-07-23"}
445
+ )
446
+ print(f"Station: {data.station.name}")
447
+ print(f"Observations: {len(data.observations)}")
448
+ ```
449
+
450
+ ## Hydrological Data
451
+
452
+ The package provides access to hydrological data from Lithuanian water monitoring stations.
453
+
454
+ ### Fetching Hydrological Stations
455
+
456
+ To get the list of all hydrological stations:
457
+
458
+ ```python
459
+ async def fetch_hydro_stations():
460
+ async with MeteoLtAPI() as api:
461
+ stations = await api.fetch_hydro_stations()
462
+ for station in stations:
463
+ print(f"{station.name} ({station.code}) - Water body: {station.water_body}")
464
+
465
+ asyncio.run(fetch_hydro_stations())
466
+ ```
467
+
468
+ ### Finding the Nearest Hydrological Station
469
+
470
+ You can find the nearest hydrological station using coordinates:
471
+
472
+ ```python
473
+ async def find_nearest_hydro_station():
474
+ async with MeteoLtAPI() as api:
475
+ # Example coordinates for Klaipėda, Lithuania
476
+ nearest_station = await api.get_nearest_hydro_station(55.6872, 21.2797)
477
+ print(f"Nearest station: {nearest_station.name}")
478
+ print(f"Water body: {nearest_station.water_body}")
479
+ print(f"Distance: approximately {nearest_station.latitude}, {nearest_station.longitude}")
480
+
481
+ asyncio.run(find_nearest_hydro_station())
482
+ ```
483
+
484
+ ### Fetching Hydrological Observations
485
+
486
+ To get water level and temperature observations for a specific station:
487
+
488
+ ```python
489
+ async def fetch_hydro_observations():
490
+ async with MeteoLtAPI() as api:
491
+ # Get observations for a station
492
+ hydro_data = await api.get_hydro_observation_data("klaipedos-juru-uosto-vms")
493
+
494
+ print(f"Station: {hydro_data.station.name}")
495
+ print(f"Water body: {hydro_data.station.water_body}")
496
+ print(f"\nRecent observations:")
497
+
498
+ for observation in hydro_data.observations[:5]:
499
+ print(f" {observation.observation_datetime}")
500
+ print(f" Water level: {observation.water_level} cm")
501
+ print(f" Water temperature: {observation.water_temperature}°C")
502
+ if observation.water_discharge:
503
+ print(f" Water discharge: {observation.water_discharge} m³/s")
504
+
505
+ asyncio.run(fetch_hydro_observations())
506
+ ```
507
+
508
+ ### Getting Observations for Nearest Station
509
+
510
+ Combine location finding with observation fetching:
511
+
512
+ ```python
513
+ async def get_nearest_station_observations():
514
+ async with MeteoLtAPI() as api:
515
+ # Find nearest hydro station to coordinates
516
+ nearest_station = await api.get_nearest_hydro_station(55.6872, 21.2797)
517
+
518
+ # Get observations for the nearest station
519
+ hydro_data = await api.get_hydro_observation_data(nearest_station.code)
520
+
521
+ print(f"Latest observations from {hydro_data.station.name}:")
522
+ if hydro_data.observations:
523
+ latest = hydro_data.observations[0]
524
+ print(f" Time: {latest.observation_datetime}")
525
+ print(f" Water level: {latest.water_level} cm")
526
+ print(f" Temperature: {latest.water_temperature}°C")
527
+
528
+ asyncio.run(get_nearest_station_observations())
311
529
  ```
312
530
 
313
531
  ## Contributing
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "meteo_lt-pkg"
3
- version = "0.5.0-beta"
3
+ version = "0.5.2"
4
4
  authors = [
5
5
  { name="Brunas", email="brunonas@gmail.com" },
6
6
  ]
File without changes
File without changes
File without changes