Как создать Python-приложение, которое предупредит о приближении астероида

Привет, Хабр! В статье я постарался показать, как объединить космос и технологии в одном приложении, которое через API оповестит пользователей по SMS о приближающемся к Земле астероиде. Подробности, как всегда, под катом.

NASA OpenAPI

NASA каждый день собирает более 15 терабайт различных данных! Вся эта информация доступна широкой аудитории бесплатно. С помощью API агентства разработчики могут использовать её для создания приложений.

Вот некоторые из доступных API, которые потенциально полезны для вашего проекта:

  • камера полихроматической визуализации Земли (EPIC) — полные изображения диска Земли:

  • отслеживание природных явлений обсерваторией EONET — прототип веб-службы, предоставляющий постоянно обновляемые метаданные природных явлений, такие как изображения штормов, собранные с поверхности Земли;

  • библиотека изображений и видео NASA — доступ к библиотеке изображений и видео;

  • звуки (бета-версия) — доступ к космическим звукам через SoundCloud с устранением некоторых шумов;

  • веб-служба объектов, сближающихся с Землёй (NeoWs) — предоставляет доступ к информации об астероидах, которые держат курс на нашу планету. Этот сервис нам и нужен.

Как подключить NASA API

Механику мы подглядели в этой статье на HackerNoon. И попробовали адаптировать шаги для аудитории Хабра.

Нужно получить доступ к необходимому нам программному интерфейсу. На официальном сайте NASA кликните по ссылке для подачи заявки на получение личного API-ключа. После отправки заявки NASA пришлёт вам ключ по электронной почте.

Экран с формой регистрации API НАСА.

Экран с формой регистрации API НАСА.

Обратите внимание, что большинство протоколов имеет ограничение API в 1 000 запросов в час. Они подходят для тестов и личного использования, но не для коммерческих целей.

Изучение данных от NASA API

Посмотрим на данные, возвращаемые API, для построения нашего варианта использования.

Запрос (GET):

  • start_date (ГГГГ-ММ-ДД) — дата начала поиска астероидов

  • end_date (ГГГГ-ММ-ДД) — дата окончания поиска астероидов

  • api_key — ключ, который вы получили по электронной почте на предыдущем шаге

Ответ:

Возвращает объект JSON с ценными данными, с которыми нужно работать для получения результата.

{
    "links": {
        "next": "http://api.nasa.gov/neo/rest/v1/feed?start_date=2023-10-17&end_date=2023-10-17&detailed=false&api_key=8DaCUyeKqnNbupBJvDO42iUMS6tqfLFK4JjM263G",
        "prev": "http://api.nasa.gov/neo/rest/v1/feed?start_date=2023-10-15&end_date=2023-10-15&detailed=false&api_key=8DaCUyeKqnNbupBJvDO42iUMS6tqfLFK4JjM263G",
        "self": "http://api.nasa.gov/neo/rest/v1/feed?start_date=2023-10-16&end_date=2023-10-16&detailed=false&api_key=8DaCUyeKqnNbupBJvDO42iUMS6tqfLFK4JjM263G"
    },
    "element_count": 10,
    "near_earth_objects": {
        "2023-10-16": [
            {
                "links": {
                    "self": "http://api.nasa.gov/neo/rest/v1/neo/2337558?api_key=8DaCUyeKqnNbupBJvDO42iUMS6tqfLFK4JjM263G"
                },
                "id": "2337558",
                "neo_reference_id": "2337558",
                "name": "337558 (2001 SG262)",
                "nasa_jpl_url": "http://ssd.jpl.nasa.gov/sbdb.cgi?sstr=2337558",
                "absolute_magnitude_h": 19.33,
                "estimated_diameter": {
                    "kilometers": {
                        "estimated_diameter_min": 0.3618719966,
                        "estimated_diameter_max": 0.8091703835
                    },
                    "meters": {
                        "estimated_diameter_min": 361.8719965994,
                        "estimated_diameter_max": 809.1703835499
                    },
                    "miles": {
                        "estimated_diameter_min": 0.2248567644,
                        "estimated_diameter_max": 0.5027950104
                    },
                    "feet": {
                        "estimated_diameter_min": 1187.2441213233,
                        "estimated_diameter_max": 2654.758561166
                    }
                },
                "is_potentially_hazardous_asteroid": true,
                "close_approach_data": [
                    {
                        "close_approach_date": "2023-10-16",
                        "close_approach_date_full": "2023-Oct-16 16:00",
                        "epoch_date_close_approach": 1697472000000,
                        "relative_velocity": {
                            "kilometers_per_second": "20.8203253059",
                            "kilometers_per_hour": "74953.171101087",
                            "miles_per_hour": "46572.9856766726"
                        },
                        "miss_distance": {
                            "astronomical": "0.2519750156",
                            "lunar": "98.0182810684",
                            "kilometers": "37694925.626976772",
                            "miles": "23422540.6669605736"
                        },
                        "orbiting_body": "Earth"
                    }
                ],
                "is_sentry_object": false
            },
            [...]

Обратите внимание на структуру near_earth_objects с необходимыми деталями:

  • estimated_diameter — диаметр астероида в метрах, километрах, милях и футах

  • relative_velocity — относительная скорость объекта

  • miss_distance — расстояние от орбитального тела

  • orbiting_body — в большинстве случаев это Земля, но при желании вы можете изучить и другие варианты

Поиск данных ближайшего астероида с помощью Python-приложения

NASA API даёт сведения об объектах, проходящих рядом. Мы найдём ближайший из них, чтобы ежедневно отправлять предупреждение в SMS. Используем для этого Python и библиотеку requests. Если у вас ещё не установлен Python, скачайте его с официального сайта.

Чтобы установить библиотеку requests, введите следующую команду:  

$ python -m pip install requests

Создайте новый файл, например alert.py. Импортируйте установленную библиотеку requests, чтобы отправлять запросы в API. Также добавьте объект date из стандартного модуля datetime, чтобы получить сегодняшнюю дату:

import requests
from datetime import date

Получите сегодняшнюю дату с помощью импортированного модуля в формате, нужном для отправки HTTP-запроса в NASA:

# Сегодняшняя дата
todays_date = date.today().strftime("%Y-%m-%d")

Пропишите API-ключ и URL-адрес для подключения к NASA API. Получить бесплатный API-ключ нужно здесь:

nasa_api_key = "NASA_API_KEY"
nasa_url = "https://api.nasa.gov/neo/rest/v1/feed?start_date=" + todays_date +"&end_date="+ todays_date + "&api_key="+nasa_api_key

Отправьте GET-запрос в NASA API и конвертируйте ответ в JSON-формат:

# Отправляем запрос в NASA API и получаем ответ в JSON
nasa_response = requests.get(nasa_url)
json_nasa_response = nasa_response.json()

В полученном от NASA ответе нужно найти ближайший к Земле астероид в массиве near_earth_objects. Напишите функцию для поиска индекса ближайшего астероида в массиве всех близких к Земле астероидов:

# Функция для нахождения индекса ближайшего к Земле астероида в массиве всех близких астероидов
def find_closest_asteroid_index(near_asteroids):
    # пустой массив для учёта дальности астероидов от Земли
    asteroids = []
    # перебираем астероиды в массиве near_earth_objects
    for i in range(0, len(near_asteroids)):
        # добавляем расстояние до Земли в массив
        asteroids.insert(i, near_asteroids[i]['close_approach_data'][0]['miss_distance']['kilometers'])
    # находим минимальное расстояние в массиве и возвращаем его индекс
    # индекс будет совпадать с индексом ближайшего астероида в near_earth_objects    
    return asteroids.index(min(asteroids))

Отправка SMS-уведомления с данными о ближайшем астероиде

Далее нужно отправить SMS-уведомление, если NASA API сообщает о том, что вблизи Земли есть астероиды. Проверьте, есть ли массив near_earth_objects в ответе от NASA API. Если есть, получите список всех ближайших астероидов и найдите индекс ближайшего с помощью функции, которую написали ранее:

# Если около Земли есть астероиды
if "near_earth_objects" in json_nasa_response:
    # Получаем список близких астероидов
    near_asteroids = json_nasa_response['near_earth_objects'][todays_date]
    # Индекс ближайшего астероида
    closest_asteroid_index = find_closest_asteroid_index(near_asteroids)

Получите данные ближайшего астероида, которые отправим в SMS-уведомлении:

    # Получаем данные астероида, которые отправим в SMS-уведомлении
    name = near_asteroids[closest_asteroid_index]['name'] #название астероида
    how_close = near_asteroids[closest_asteroid_index]['close_approach_data'][0]['miss_distance']['kilometers'] #расстояние от Земли
    diameter =  near_asteroids[closest_asteroid_index]['estimated_diameter']['meters']['estimated_diameter_max'] #диаметр астероида

Переведите полученные данные в строку и сформируйте текст сообщения:

    # Форматируем данные в строку
    how_close_str = str(round(float(how_close)))
    diameter_str = str(round(diameter))
   
    # Формируем сообщение
    alert ="Ближайший астероид сегодня - " + name + ". Он находится в " + how_close_str + " км от Земли. Его диаметр составляет " + diameter_str + " метров."

Теперь можно перейти к отправке SMS-уведомления с помощью Exolve SMS API. Для этого нам понадобятся:

Добавьте в код номер Exolve, URL-адрес, API-ключ и номер получателя:

    # Настройки подключения к Exolve
    exolve_number = "7999XXXXXXX"
    exolve_url = "https://api.exolve.ru/messaging/v1/SendSMS"
    recipient_number = "7924XXXXXXX"
    exolve_api_key = "EXOLVE_API_KEY"

Сделайте запрос к Exolve API с помощью библиотеки requests, чтобы отправить SMS-уведомление на указанный номер со сформированным ранее текстом сообщения с данными о ближайшем астероиде:

    # Отправляем запрос в EXOLVE SMS API и получаем ответ в JSON
    exolve_response = requests.post(exolve_url,
    headers = {"Authorization": "Bearer " + exolve_api_key},
    json = {
        "number": exolve_number,
        "destination": recipient_number,
        "text": alert
    })
    json_exolve_response = exolve_response.json()
    print(json_exolve_response) # message_id или ошибка отправки

Запустите код. Вы должны получить похожее SMS-уведомление:

SMS-уведомление

SMS-уведомление

Резюме

Подытожим, что мы сделали:

  1. Получили ключ API для портала NASA OpenAPI.

  2. Изучили API NeoWs, который даёт доступ к информации об астероидах, направляющихся к Земле.

  3. Нашли ближайший к нашей планете объект из всех тех, что могли пройти поблизости.

  4. Отправили SMS-уведомление, чтобы предупредить себя об этой встрече.

Теперь можно спать спокойно, учитывая, что вы знаете о каждом большом объекте, летящем к Земле.

Исходный код приложения можно найти на GitHub.

© Habrahabr.ru