
Jest wiele serwisów dostarczających informacje o pogodzie, ale któremu z nich można zaufać? Gdy zacząłem często jeździć na rowerze, chciałem mieć najbardziej precyzyjne informacje o warunkach pogodowych w miejscu, w którym jeżdżę.
Pierwszą myślą było zbudowanie małej stacji pogodowej DIY z czujnikami i uzyskiwanie danych z niej. Ale nie chciałem „wynajdywać koła na nowo” i jako źródło sprawdzonych danych wybrałem informacje pogodowe używane w cywilnej aviacji, a mianowicie METAR (METeorological Aerodrome Report) i TAF (TAF — Terminal Aerodrome Forecast). W lotnictwie życie setek ludzi zależy od pogody, dlatego prognozy są maksymalnie precyzyjne.
Te informacje są w trybie ciągłym przekazywane głosem na każdym nowoczesnym lotnisku w formie ATIS (Automatic Terminal Information Service) i VOLMET (od franc. vol — lot i météo — pogoda). Pierwszy dostarcza informacje o rzeczywistej pogodzie na lotnisku, a drugi — prognozę na najbliższe 24-30 godzin, przy czym nie tylko na lotnisku nadającym, ale także na innych.
Przykład pracy ATIS w porcie lotniczym Wnukowo:
Przykład pracy VOLMET w porcie lotniczym Wnukowo
Niewygodnie jest za każdym razem nosić ze sobą skanery radiowe lub transiwery na odpowiednim paśmie, dlatego chciałem stworzyć bota w Telegramie, który na naciśnięcie przycisku pozwala uzyskać taką samą prognozę. Niecelowe jest wydzielanie do tego osobnego serwera, jak i kierowanie zapytań na domową Raspberry.
Dlatego jako backend postanowiłem użyć usługi . Liczba zapytań będzie znikoma, dlatego taka usługa praktycznie nic nie kosztuje (wg moich obliczeń wyniesie 22 rubli za 100 000 zapytań).
Przygotowanie backendu
Tworzenie funkcji
W panelu sterowania otwieramy widok Platforma chmurowa i tworzymy nowy projekt:

Po utworzeniu projektu przechodzimy do sekcji Funkcje:

Klikamy przycisk Utwórz funkcję i nadajemy jej odpowiednią nazwę:

Po naciśnięciu Utwórz funkcję pojawi się widok utworzonej funkcji:

Zanim przystąpimy do tworzenia kodu w Pythonie, należy stworzyć bota w Telegramie. Nie będę opisywał, jak się to robi — szczegółowa instrukcja jest . Najważniejsze dla nas — token utworzonego bota.
Przygotowujemy kod
Jako źródło wiarygodnych danych wybrałem Narodową Administrację Oceaniczną i Atmosferyczną USA (ang. National Oceanic and Atmospheric Administration, NOAA). Ta agencja naukowa aktualizuje dane na swoim serwerze w formacie TXT w czasie rzeczywistym.
Link do uzyskania danych METAR (zwróć uwagę na wielkość liter):
https://tgftp.nws.noaa.gov/data/observations/metar/stations/.TXTW moim przypadku najbliższym lotniskiem jest Wnukowo, jego kod według ICAO to UUWW. Przejście na wygenerowany URL zwróci następujące:
2020/08/10 11:30
UUWW 101130Z 31004MPS 9999 SCT048 24/13 Q1014 R01/000070 NOSIG
Pierwszy wiersz to czas obowiązywania prognozy według Greenwich. Drugi wiersz to podsumowanie faktycznej pogody. Piloci cywilni bez problemu zrozumieją, co oznacza ten wiersz, ale potrzebujemy jego wyjaśnienia:
- [UUWW] — Wnukowo, miasto Moskwa (Rosja — RU);
- [101130Z] — 10. dzień miesiąca, godzina 11:30 według Greenwich;
- [31004MPS] — kierunek wiatru 310 stopni, prędkość 4 m/s;
- [9999] — widoczność pozioma 10 km i więcej;
- [SCT048] — rozproszone chmury na wysokości 4800 stóp (~1584m);
- [24/13] — temperatura 24°C, punkt rosy 13°C;
- [Q1014] — ciśnienie (QNH) 1014 hektopaskali (750 mm rt. czt.);
- [R01/000070] — współczynnik tarcia na pasie 01 to 0,70;
- [NOSIG] — bez znaczących zmian.
Przechodzimy do pisania kodu. Najpierw trzeba zaimportować funkcje request i pytaf:
from urllib import request
import pytafNależy określić zmienne i przygotować funkcję dekodowania:
URL_METAR = "https://tgftp.nws.noaa.gov/data/observations/metar/stations/UUWW.TXT"
URL_TAF = "https://tgftp.nws.noaa.gov/data/forecasts/taf/stations/UUWW.TXT"
def parse_data(code):
code = code.split('n')[1]
return pytaf.Decoder(pytaf.TAF(code)).decode_taf()Przechodzimy do TAF (wielkość liter jest również ważna).
https://tgftp.nws.noaa.gov/data/forecasts/taf/stations/.TXTJak w poprzednim przykładzie, przyjrzymy się prognozie w porcie lotniczym Wnukowo:
2020/08/10 12:21
TAF UUWW 101050Z 1012/1112 28003G10MPS 9999 SCT030 TX25/1012Z TN15/1103Z
TEMPO 1012/1020 -TSRA BKN020CB
BECMG 1020/1021 FEW007 BKN016
TEMPO 1021/1106 -SHRA BKN020CB PROB40
TEMPO 1021/1106 -TSRA BKN020CB
BECMG 1101/1103 34006G13MPS
Szczególnie zwrócimy uwagę na wiersze TEMPO i BECMG. TEMPO oznacza, że faktyczna pogoda w podanym okresie będzie się okresowo zmieniać. BECMG — pogoda stopniowo zmieni się w podanym czasie.
Oznacza to, że wiersz:
TEMPO 1012/1020 -TSRA BKN020CBBędzie oznaczać:
- [1012/1020] — w okresie od 12 do 20 godzin (według Greenwich);
- [-TSRA] — burza (TS = thunderstorm) z deszczem (RA = rain) o niewielkiej intensywności (znak minus);
- [BKN020CB] — znaczne (BKN = broken), chmurowo-deszczowe (CB = cumulonimbus) zachmurzenie na wysokości 2000 stóp (610 metrów) nad poziomem morza.
Terminów oznaczających zjawiska pogodowe jest dość dużo i trudno jest je zapamiętać. Kod do zapytania TAF pisze się w podobny sposób.
Wgrywamy kod do chmury.
Aby nie tracić czasu, weźmy szablon bota telegramowego z naszego repozytorium. . Jest tam wstępnie przygotowany requirements.txt i setup.py z poprawną strukturą katalogów.
Ponieważ w kodzie będziemy odnosić się do modułu pytaf, jego wersję należy od razu dodać w requirements.txt
pytaf~=1.2.1- Przechodzimy do edytowania bot/tele_bot.py. Usuwamy wszystko zbędne i dopisujemy nasz kod.
import os
from urllib import request
import telebot
import pytaf
TOKEN = os.environ.get('TOKEN')
URL_METAR = "https://tgftp.nws.noaa.gov/data/observations/metar/stations/UUWW.TXT"
URL_TAF = "https://tgftp.nws.noaa.gov/data/forecasts/taf/stations/UUWW.TXT"
bot = telebot.TeleBot(token=TOKEN, threaded=False)
keyboard = telebot.types.ReplyKeyboardMarkup(resize_keyboard=True)
keyboard.row('start', 'get_metar', 'get_taf')
def start(message):
msg = "Cześć. To bot do uzyskiwania prognozy pogody dla lotnictwa "
"z serwerów NOAA. Bot jest ustawiony na lotnisko Wnukowo (UUWW)."
bot.send_message(message.chat.id, msg, reply_markup=keyboard)
def parse_data(code):
code = code.split('n')[1]
return pytaf.Decoder(pytaf.TAF(code)).decode_taf()
def get_metar(message):
# Pobierz informacje z serwera.
code = request.urlopen(URL_METAR).read().decode('utf-8')
# Wyślij sformatowaną odpowiedź.
bot.send_message(message.chat.id, parse_data(code), reply_markup=keyboard)
def get_taf(message):
# Pobierz informacje z serwera.
code = request.urlopen(URL_TAF).read().decode('utf-8')
# Wyślij sformatowaną odpowiedź.
bot.send_message(message.chat.id, parse_data(code), reply_markup=keyboard)
def route_command(command, message):
"""
Router poleceń.
"""
if command == 'start':
return start(message)
elif command == 'get_metar':
return get_metar(message)
elif command == 'get_taf':
return get_taf(message)
def main(**kwargs):
"""
Punkt wejścia do środowiska bezserwerowego.
"""
print(f'Otrzymano: "{kwargs}"')
message = telebot.types.Update.de_json(kwargs)
message = message.message or message.edited_message
if message and message.text and message.text[0] == '/':
print(f'Echo na "{message.text}"')
route_command(message.text.lower(), message)
- Pakujemy cały katalog w archiwum ZIP i przechodzimy do panelu sterowania do stworzonej funkcji.
- Klikamy Edytować i ładujemy archiwum z kodem.

- Wypełniamy względną ścieżkę do pliku tele_bot (rozszerzenie .py nie jest konieczne) i funkcję end-point (w podanym przykładzie jest to main).
- W sekcji Zmienna środowiskowa piszemy zmienną TOKEN i przypisujemy jej token odpowiedniego bota telegramowego.
- Klikamy Zapisz i uruchom, po czym przechodzimy do sekcji Wyzwalacze.
- Ustawiamy przełącznik HTTP-Żądanie, aby uczynić zapytanie publicznym.

Mamy już adres URL do publicznego wywołania funkcji. Teraz wystarczy . Znajdź naszego bota na Telegramie i zarejestruj swojego bota komendą:
/setwebhook <you bot token> <public URL of your function>Wynik
Jeśli wszystko zostało zrobione poprawnie, twój bot od razu zacznie działać i wyświetlać aktualne podsumowanie prognozy pogody lotniczej bezpośrednio w komunikatorze.

Oczywiście, kod można rozwijać, jednak nawet w obecnym stanie jest wystarczający, aby uzyskać najdokładniejszą pogodę i prognozę z zaufanego źródła.
Pełną wersję kodu znajdziesz w naszym .
Źródło: habr.com
