Сервісів, які надають інформацію про погоду, досить багато, ось тільки якому з них вірити? Коли я став часто їздити на велосипеді, мені захотілося мати найточнішу інформацію про погодні умови в тому місці, де я катаюся.
Першою думкою було зібрати невелику DIY погодну станцію з датчиками та отримувати дані з неї. Але я не став «винаходити велосипед» і як джерело перевірених даних вибрав погодну інформацію, яка використовується в цивільній авіації, а саме METAR (METeorological Aerodrome Report) та TAF (TAF - Terminal Aerodrome Forecast). В авіації від погоди залежить життя сотень людей, тому прогнози максимально точні.
Ця інформація у цілодобовому режимі транслюється голосом на кожному сучасному аеродромі у вигляді АТІС (Automatic Terminal Information Service) та VOLMET (Від франц. про - політ і Метео - Погода). Перший надає інформацію про фактичну погоду на аеродромі, а другий прогноз на найближчі 24-30 годин, причому не тільки на аеродромі трансляції, а й на інших.
Приклад роботи ATIS аеропорту Внуково:
Приклад роботи VOLMET аеропорту Внуково
Щоразу тягати з собою радіосканнер або трансівер на відповідний діапазон незручно, і мені захотілося створити бота в Telegram, який натисканням кнопки дозволяє отримати такий же прогноз. Виділяти під це окремий сервер як мінімум недоцільно, так само як і ганяти запити на домашню Raspberry.
Тому як бекенд я вирішив використовувати сервіс
Підготовка бекенда
Створення функції
В панелі управління
Після того, як проект створений, переходимо в розділ Функції:
натискаємо кнопку Створити функцію і задаємо їй потрібне ім'я:
Після натискання Створити функцію у нас з'явиться уявлення створеної функції:
Перед тим, як розпочати створення коду на Python, потрібно створити бота в Telegram. Розписувати, як це робиться, я не буду - детальна інструкція є
Готуємо код
Як джерело надійних даних я вибрав Національне управління океанічних та атмосферних досліджень США (National Oceanic and Atmospheric Administration, NOAA). Це наукове агентство реально оновлює дані на своєму сервері у форматі TXT.
Посилання для отримання даних METAR (зверніть увагу на регістр):
https://tgftp.nws.noaa.gov/data/observations/metar/stations/<код аэропорта по ICAO>.TXT
У моєму випадку найближчим аеропортом є Внуково, його код за ICAO UUWW. Перехід на сформовану URL видасть наступне:
2020/08/10 11:30
UUWW 101130Z 31004MPS 9999 SCT048 24/13 Q1014 R01/000070 NOSIG
Перший рядок – час актуальності прогнозу щодо Грінвіча. Другий рядок – зведення про фактичну погоду. Пілоти цивільної авіації без проблем зрозуміють, що означає цей рядок, проте нам потрібне розшифрування:
- [UUWW] - Внуково, місто Москва (Росія - RU);
- [101130Z] - 10-й день місяця, 11 годин 30 хвилин за Грінвічем;
- [31004MPS] - Напрямок вітру 310 градусів, швидкість 4 м / с;
- [9999] - Горизонтальна видимість 10 км і більше;
- [SCT048] - розсіяні/розкидані хмари на висоті 4800 футів (~1584м);
- [24/13] - температура 24 ° C, точка роси 13 ° C;
- [Q1014] - Тиск (QNH) 1014 гектопаскалів (750 мм рт. ст.);
- [R01/000070] - Коефіцієнт зчеплення на смузі 01 - 0,70;
- [NOSIG] - Без істотних змін.
Приступаємо до написання програмного коду. Для початку потрібно імпортувати функції запросити и pytaf:
from urllib import request
import pytaf
Вказати змінні та підготувати функцію декодування:
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()
Перейдемо до TAF (реєстр також важливий).
https://tgftp.nws.noaa.gov/data/forecasts/taf/stations/<код аэропорта по ICAO>.TXT
Як і в попередньому прикладі, подивимося прогноз в аеропорту Внуково:
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
Особливо звернемо увагу на рядки TEMPO и BECMG. TEMPO означає те, що фактична погода у вказаний проміжок періодично змінюватиметься. BECMG – погода поступово зміниться у вказаний проміжок часу.
Тобто рядок:
TEMPO 1012/1020 -TSRA BKN020CB
Означатиме:
- [1012/1020] - Проміжок з 12 до 20 годин (за Грінвічем);
- [-TSRA] - Гроза (TS = thunderstorm) з дощем (RA = rain) невеликої інтенсивності (знак мінус);
- [BKN020CB] - Значна (BKN = broken), купо-дощова (CB = cumulonimbus) хмарність на висоті 2000 футів (610 метрів) над рівнем моря.
Термінів, що означають погодні явища, досить багато, і запам'ятати їх важко. Код запиту TAF пишеться аналогічним чином.
Заливаємо код у хмару
Щоб не марнувати час, візьмемо шаблон телеграм-бота з нашого репозиторію
Оскільки в коді ми звертатимемося до модуля pytaf, то його версію слід відразу додати до вимоги.txt
pytaf~=1.2.1
- Переходимо до редагування bot/tele_bot.py. Забираємо все зайве та дописуємо наш код.
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 = "Привет. Это бот для получения авиационного прогноза погоды "
"с серверов NOAA. Бот настроен на аэропорт Внуково (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):
# Fetch info from server.
code = request.urlopen(URL_METAR).read().decode('utf-8')
# Send formatted answer.
bot.send_message(message.chat.id, parse_data(code), reply_markup=keyboard)
def get_taf(message):
# Fetch info from server.
code = request.urlopen(URL_TAF).read().decode('utf-8')
# Send formatted answer.
bot.send_message(message.chat.id, parse_data(code), reply_markup=keyboard)
def route_command(command, message):
"""
Commands router.
"""
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):
"""
Serverless environment entry point.
"""
print(f'Received: "{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 on "{message.text}"')
route_command(message.text.lower(), message)
- Пакуємо всю директорію в ZIP-архів і переходимо в панель управління до створеної функції.
- натискаємо Редагувати та завантажуємо архів з кодом.
- Заповнюємо відносний шлях у файлі tele_bot (розширення .py можна не вказувати) та ендпойнт-функцію (у наведеному прикладі це основний).
- У розділі Змінні оточення пишемо змінну ТОКЕН і привласнюємо їй токен потрібного телеграм-бота.
- натискаємо Зберегти та розгорнути, після чого переходимо до розділу Тригери.
- Ставимо перемикач HTTP-запит, щоб зробити запит публічним.
У нас з'явилася URL-адреса для публічного виклику функції. Залишилось лише
/setwebhook <you bot token> <public URL of your function>
Результат
Якщо все зроблено правильно, то ваш бот відразу почне працювати і відображати актуальне зведення авіаційної погоди прямо в месенджері.
Зрозуміло, код можна доопрацьовувати, проте навіть у поточному стані його достатньо, щоб дізнатися найточнішу погоду та прогноз із перевіреного джерела.
Повну версію коду ви знайдете в нашому
Джерело: habr.com