Raspberry Pi Pico W: начало работы с HTTP GET-запросами (MicroPython)

Это руководство представляет собой введение в HTTP GET-запросы с Raspberry Pi Pico W. HTTP-запросы являются основой для взаимодействия с веб-сервисами, получения данных из внешних источников, интеграции с веб-API для доступа к сторонним сервисам и многого другого.

В этом руководстве вы изучите основные концепции HTTP GET-запросов и протестируете несколько простых примеров для получения данных из интернета.

Raspberry Pi Pico W: начало работы с HTTP GET-запросами MicroPython

Когда речь идет об IoT-проектах, HTTP-запросы являются основой для взаимодействия с веб-сервисами, получения данных из внешних источников, интеграции с веб-API для доступа к веб-сервисам или даже удаленного управления вашим Pico с помощью сторонних внешних платформ.

В этом руководстве мы рассмотрим следующие темы:

Необходимые условия

Прежде чем продолжить, убедитесь, что выполнены следующие условия:

Прошивка MicroPython

Для выполнения этого руководства вам необходима прошивка MicroPython, установленная на вашу плату Raspberry Pi Pico. Вам также понадобится IDE для написания и загрузки кода на плату.

Логотип MicroPython

Рекомендуемая IDE для MicroPython на Raspberry Pi Pico — Thonny IDE. Следуйте следующему руководству, чтобы узнать, как установить Thonny IDE, прошить MicroPython и загрузить код на плату.

В качестве альтернативы, если вам нравится программировать в VS Code, вы можете начать со следующего руководства:

Что такое HTTP-запросы?

Наиболее распространенный способ обмена данными с другим компьютером (сервером) в интернете — использование протокола HTTP.

HTTP (Hypertext Transfer Protocol) работает по модели клиент-сервер. В этой модели клиент взаимодействует с сервером с помощью HTTP-запросов. HTTP-запрос — это сообщение, отправляемое клиентом на сервер, обычно для запроса определенного действия или получения информации. Сервер отправляет ответ обратно клиенту также через HTTP.

Raspberry Pi Pico HTTP GET-запрос — модель клиент-сервер
  • Клиент: инициирует коммуникацию через запрос.

  • Сервер: получает и обрабатывает запрос и отправляет ответ в ответ.

Raspberry Pi Pico может выступать как в роли клиента, так и сервера. Когда он является клиентом, он отправляет запросы серверам. Когда он является :doc:`сервером </raspberry/pico/raspberry-pi-pico-web-server-micropython/index>`_, он обрабатывает запросы клиентов.

В этом руководстве мы рассмотрим Raspberry Pi Pico в роли HTTP-клиента.

Вот несколько примеров того, что можно делать с помощью HTTP-запросов на Pico:

  • Получать данные из интернета: например, время, текущую погоду, курсы акций, обновления трафика и многое другое…

  • Логирование данных: отправлять данные в облако для сохранения ваших данных онлайн;

  • Удаленное управление Raspberry Pi Pico: взаимодействуя с IoT-платформами, такими как Adafruit IO, Node-RED и другими — вы можете удаленно взаимодействовать с вашей платой, обмениваясь данными через HTTP-запросы;

  • Взаимодействие со сторонними сервисами для отправки уведомлений: SMS, электронная почта, push-уведомления и многое другое…

Технический обзор HTTP-запросов

Давайте кратко рассмотрим технические аспекты HTTP-запросов. Если вы впервые сталкиваетесь с HTTP-запросами в техническом плане и это кажется запутанным, это совершенно нормально.

Но не волнуйтесь, существуют модули MicroPython, которые абстрагируют всю техническую часть, делая создание и обработку HTTP-запросов очень простым. Кроме того, для получения дополнительной информации о технических аспектах HTTP-запросов мы рекомендуем следующие ресурсы:

HTTP-запросы

HTTP-запрос состоит из нескольких частей. Основные элементы: строка запроса, заголовки и тело.

Строка запроса

Строка запроса определяет HTTP-метод, запрашиваемый ресурс (URL) и версию используемого протокола HTTP. Распространенные HTTP-методы включают GET, POST, PUT и DELETE. Например:

GET /path/to/resource HTTP/1.1

Заголовки

Заголовки предоставляют информацию о запросе. Они могут включать хост, которому клиент отправляет запрос, тип отправляемого или принимаемого контента, user-agent (идентифицирует клиента, выполняющего запрос) и другое. Например:

Host: example.com
User-Agent: RaspberryPiPico
Accept: application/json

Тело

Тело — это необязательный контент, содержащий данные или информацию, которые мы хотим отправить на сервер. Оно используется в POST и PUT запросах. Например:

POST /submit-form HTTP/1.1
Content-Type: application/x-www-form-urlencoded
username=johndoe&password=secretpassword

Методы HTTP-запросов

Выбор HTTP-метода в запросе указывает на предполагаемое действие, которое должно быть выполнено на сервере. Некоторые часто используемые методы включают:

  • GET: получить данные с сервера.

  • POST: отправить данные для обработки на указанный ресурс.

  • PUT: обновить ресурс на сервере.

  • DELETE: удалить ресурс с сервера.

В этом руководстве мы сосредоточимся на использовании GET-запросов с Raspberry Pi Pico.

Коды состояния HTTP

После получения HTTP-запроса сервер отвечает кодом состояния HTTP, указывающим результат запроса. Коды состояния делятся на категории: 2xx (успешные), 3xx (перенаправление), 4xx (ошибка клиента) и 5xx (ошибка сервера). Некоторые из наиболее распространенных:

  • 200 OK: запрос выполнен успешно.

  • 404 Not Found: запрашиваемый ресурс не найден.

HTTP-запросы с Raspberry Pi Pico

Самый простой способ выполнять HTTP-запросы с Raspberry Pi Pico — использовать библиотеку requests, которая использует высокоуровневый подход. Она очень похожа на библиотеку Python requests, но более ограничена.

Вы также можете использовать модуль socket, но это более низкоуровневый подход и он не так удобен для начинающих.

Следующий код — базовый пример того, как выполнить простой HTTP-запрос к веб-сайту Google с помощью библиотеки requests.

import network
import requests

# Учетные данные Wi-Fi
ssid = 'REPLACE_WITH_YOUR_SSID'
password = 'REPLACE_WITH_YOUR_PASSWORD'

# Подключение к сети
wlan = network.WLAN(network.STA_IF)
wlan.active(True)

# Подключение к вашей сети
wlan.connect(ssid, password)

# Выполнение GET-запроса
response = requests.get("http://www.google.com")
# Получение кода ответа
response_code = response.status_code
# Получение содержимого ответа
response_content = response.content

# Вывод результатов
print('Response code: ', response_code)
print('Response content:', response_content)

Как работает код

Начните с импорта библиотек network и requests.

import network
import requests

Замените 'REPLACE_WITH_YOUR_SSID' и 'REPLACE_WITH_YOUR_PASSWORD' на имя вашей Wi-Fi сети (SSID) и пароль.

ssid = 'REPLACE_WITH_YOUR_SSID'
password = 'REPLACE_WITH_YOUR_PASSWORD'

Затем инициализируйте Wi-Fi интерфейс, активируйте его и подключитесь к вашей сети, используя SSID и пароль, определенные ранее.

# Подключение к сети
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
# Подключение к вашей сети
wlan.connect(ssid, password)

Наконец, выполните запрос. Используя модуль requests и метод get(), код отправляет GET-запрос на веб-сайт Google. Ответ от сервера сохраняется в переменной response.

response = requests.get("http://www.google.com")

Ответ — это объект типа Response. Этот объект имеет несколько атрибутов, к которым вы можете обратиться и которые могут быть полезны. Например:

  • response.status_code: возвращает целочисленное значение, представляющее статус ответа;

  • response.content: возвращает фактическое содержимое в байтах;

  • response.text: возвращает содержимое, преобразованное в строку, используя кодировку символов, такую как UTF-8;

  • response.json(): возвращает ответ в виде JSON-объекта (словаря);

  • response.headers(): доступ к информации о заголовках ответа.

После получения ответа мы получаем статус ответа с помощью атрибута status_code.

response_code = response.status_code

Сохраняем содержимое ответа в переменной response_content с помощью атрибута content.

response_content = response.content

Наконец, выводим код состояния и содержимое запроса в Shell.

print('Response code: ', response_code)
print('Response content:', response_content)

Тестирование кода

После ввода учетных данных вашей сети вы можете запустить предыдущий код на вашем Raspberry Pi Pico.

Если все пройдет как ожидается, код ответа должен быть 200, и он выведет содержимое веб-страницы Google.

Raspberry Pi Pico HTTP GET-запрос к Google — ответ

Получение данных из интернета с помощью HTTP GET-запросов

Теперь, когда вы знаете, как выполнить базовый HTTP GET-запрос, мы покажем вам различные примеры получения данных из интернета. Мы создадим два разных примера:

Пример 1: Прогноз погоды

В этом примере мы будем использовать Weather API для создания прогноза погоды. Этот API бесплатный и предоставляет полезную информацию о погоде практически в любой точке мира.

Пример прогноза погоды

Мы получим данные о погоде для вашего местоположения и отобразим их в Shell.

Получение API-ключа

  1. Перейдите на веб-сайт Weather API: https://www.weatherapi.com/

  2. Зарегистрируйтесь, чтобы создать учетную запись.

  3. После подтверждения учетной записи войдите в свой аккаунт.

  4. На панели управления по адресу https://www.weatherapi.com/my/ вы найдете свой API-ключ (даже если написано, что пробный период закончится, вы можете продолжать использовать свой API-ключ бесплатно).

Ключ Weather API

Скопируйте API-ключ в надежное место, потому что он понадобится вам позже.

Чтобы получить информацию о погоде в выбранном вами местоположении, введите следующий URL в вашем веб-браузере, подставив ваше местоположение и API-ключ в соответствующие места:

https://api.weatherapi.com/v1/current.json?q=YOUR_LOCATION+&key=YOUR_API_KEY'

Например, в моем случае:

https://api.weatherapi.com/v1/current.json?q=Oporto+&key=d1578a064b07453c917164350240106'

Скопируйте ваш URL и вставьте его в браузер, и API вернет информацию, соответствующую вашей местной погоде. Например:

{
  "location": {
    "name": "Oporto",
    "region": "Porto",
    "country": "Portugal",
    "lat": 41.15,
    "lon": -8.62,
    "tz_id": "Europe/Lisbon",
    "localtime_epoch": 1719843562,
    "localtime": "2024-07-01 15:19"
  },
  "current": {
    "last_updated_epoch": 1719843300,
    "last_updated": "2024-07-01 15:15",
    "temp_c": 22.3,
    "temp_f": 72.1,
    "is_day": 1,
    "condition": {
      "text": "Sunny",
      "icon": "//cdn.weatherapi.com/weather/64x64/day/113.png",
      "code": 1000
    },
    "wind_mph": 10.5,
    "wind_kph": 16.9,
    "wind_degree": 310,
    "wind_dir": "NW",
    "pressure_mb": 1021,
    "pressure_in": 30.15,
    "precip_mm": 0,
    "precip_in": 0,
    "humidity": 69,
    "cloud": 0,
    "feelslike_c": 24.7,
    "feelslike_f": 76.4,
    "windchill_c": 21.9,
    "windchill_f": 71.5,
    "heatindex_c": 24.6,
    "heatindex_f": 76.2,
    "dewpoint_c": 15,
    "dewpoint_f": 58.9,
    "vis_km": 10,
    "vis_miles": 6,
    "uv": 6,
    "gust_mph": 15.4,
    "gust_kph": 24.7
  }
}

Код – HTTP GET-запрос: Weather API

Следующий код выполняет запрос к Weather API для получения данных о погоде в вашем местоположении. Затем мы отображаем данные в Shell. Мы выведем информацию о текущей погоде, температуре, влажности и осадках.

import network
import time
import requests

# Учетные данные Wi-Fi
ssid = 'REPLACE_WITH_YOUR_SSID'
password = 'REPLACE_WITH_YOUR_PASSWORD'

api_key = 'REPLACE_WITH_YOUR_API_KEY'
location ='Oporto'

# URL запроса
url = f'https://api.weatherapi.com/v1/current.json?q={location}+&key={api_key}'

def init_wifi(ssid, password):# Инициализация Wi-Fi интерфейса
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)
    # Подключение к вашей сети
    wlan.connect(ssid, password)
    # Ожидание подключения к Wi-Fi
    connection_timeout = 10
    while connection_timeout > 0:
        if wlan.status() >= 3:
            break
        connection_timeout -= 1
        print('Waiting for Wi-Fi connection...')
        time.sleep(1)
    # Проверка успешности подключения
    if wlan.status() != 3:
        return False
    else:
        print('Connection successful!')
        network_info = wlan.ifconfig()
        print('IP address:', network_info[0])
        return True

if init_wifi(ssid, password):
    try:
        # Выполнение запроса
        response = requests.get(url)
        # Вывод кода ответа
        print('Response code: ', response.status_code)

        # Получение содержимого ответа
        weather = response.json()
        # Закрытие запроса
        response.close()

        # Вывод всех данных о погоде
        print('Weather JSON: ', weather)

        # Получение конкретных данных о погоде
        weather_description = weather['current']['condition']['text']
        print('Current weather: ', weather_description)

        # Температура и влажность
        temperature_c = weather['current']['temp_c']
        temperature_f = weather['current']['temp_f']
        humidity = weather['current']['humidity']
        print(f'Temperature in Celsius: {temperature_c:.2f}')
        print(f'Temperature in Fahrenheit: {temperature_f:.2f}')
        print(f'Humidity (%): {humidity:.2f}')

        # Осадки
        precipitation = weather['current']['precip_mm']
        print(f'Precipitation in mm: {precipitation}')

        # Ветер
        wind_speed = weather['current']['wind_kph']
        print('Wind speed in kph:', wind_speed)

    except Exception as e:
        # Обработка исключений во время запроса
        print('Error during request:', e)

Как работает код

Давайте кратко рассмотрим, как работает этот код.

Чтобы код заработал, сначала вам нужно ввести учетные данные вашей сети для подключения Raspberry Pi Pico к интернету.

# Учетные данные Wi-Fi
ssid = 'REPLACE_WITH_YOUR_SSID'
password = 'REPLACE_WITH_YOUR_PASSWORD'

Затем введите ваш API-ключ Weather API и город, откуда вы хотите получить данные.

api_key = 'REPLACE_WITH_YOUR_API_KEY'
city = 'REPLACE_WITH_YOUR_CITY'

Мы сохраняем URL запроса в переменной url. Это f-строка с заполнителями, чтобы URL обновлялся вашими данными во время выполнения.

url = f'https://api.weatherapi.com/v1/current.json?q={location}+&key={api_key}'

Мы создаем функцию init_wifi(), которая подключается к вашей локальной сети. Эта функция возвращает True, если подключение к Wi-Fi прошло успешно, или False, если нет.

def init_wifi(ssid, password):
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)
    # Подключение к вашей сети
    wlan.connect(ssid, password)
    # Ожидание подключения к Wi-Fi
    connection_timeout = 10
    while connection_timeout > 0:
        if wlan.status() >= 3:
            break
        connection_timeout -= 1
        print('Waiting for Wi-Fi connection...')
        time.sleep(1)
    # Проверка успешности подключения
    if wlan.status() != 3:
        return False
    else:
        print('Connection successful!')
        network_info = wlan.ifconfig()
        print('IP address:', network_info[0])
        return True

Затем мы подключаемся к Wi-Fi и проверяем успешность подключения перед выполнением запроса.

if init_wifi(ssid, password):

Выполнение запроса так же просто, как использование метода get() модуля requests и передача URL в качестве аргумента.

response = requests.get(url)

Это вернет JSON-объект. Поэтому мы можем преобразовать результат в словарь Python с помощью метода json().

weather = response.json()

Затем мы закрываем соединение для освобождения ресурсов.

# Закрытие запроса
response.close()

Теперь все данные, которые вы видели в вашем веб-браузере на предыдущих шагах, сохранены в переменной weather.

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

# Получение конкретных данных о погоде
weather_description = weather['current']['condition']['text']
print('Current weather: ', weather_description)

# Температура и влажность
temperature_c = weather['current']['temp_c']
temperature_f = weather['current']['temp_f']
humidity = weather['current']['humidity']
print(f'Temperature in Celsius: {temperature_c:.2f}')
print(f'Temperature in Fahrenheit: {temperature_f:.2f}')
print(f'Humidity (%): {humidity:.2f}')

# Осадки
precipitation = weather['current']['precip_mm']
print(f'Precipitation in mm: {precipitation}')

# Ветер
wind_speed = weather['current']['wind_kph']
print('Wind speed in kph:', wind_speed)

Тестирование кода

После ввода учетных данных вашей сети, API-ключа и города, вы можете запустить код на вашем Raspberry Pi Pico.

Вы должны получить результат, похожий на скриншот ниже, но с информацией для вашего выбранного местоположения.

Получение данных о погоде с Weather API с помощью Raspberry Pi Pico

Вы можете развить этот проект дальше, отображая данные на дисплее, например LCD или OLED. Вы можете создать цикл while или прерывание по таймеру для периодического запроса данных, или даже запрашивать данные для нескольких местоположений, просто меняя значение переменной city.

Пример 2: Текущий курс биткоина

Логотип Bitcoin — получение курса с RPi Pico

В этом примере мы будем запрашивать и отображать текущий курс биткоина. CoinGecko имеет эндпоинт, который можно использовать для запросов, возвращающих текущую цену биткоина в USD:

https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd

Если вы откроете этот URL в вашем веб-браузере, вы должны получить что-то вроде:

{"bitcoin":{"usd":62748}}

Теперь, используя этот URL, мы можем легко получить курс биткоина с помощью нашего Raspberry Pi Pico.

import network
import requests
from time import sleep

# Учетные данные Wi-Fi
ssid = 'REPLACE_WITH_YOUR_SSID'
password = 'REPLACE_WITH_YOUR_PASSWORD'

# URL запроса
url = 'https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd'

def init_wifi(ssid, password):# Инициализация Wi-Fi интерфейса
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)
    # Подключение к вашей сети
    wlan.connect(ssid, password)
    # Ожидание подключения к Wi-Fi
    connection_timeout = 10
    while connection_timeout > 0:
        if wlan.status() >= 3:
            break
        connection_timeout -= 1
        print('Waiting for Wi-Fi connection...')
        sleep(1)
    # Проверка успешности подключения
    if wlan.status() != 3:
        return False
    else:
        print('Connection successful!')
        network_info = wlan.ifconfig()
        print('IP address:', network_info[0])
        return True

if init_wifi(ssid, password):
    try:
        # Выполнение запроса
        response = requests.get(url)
        # Вывод кода ответа
        print('Response code: ', response.status_code)

        # Получение содержимого ответа
        bitcoin = response.json()
        # Закрытие запроса
        response.close()

        # Вывод курса биткоина
        bitcoin_price = bitcoin['bitcoin']['usd']
        print('Bitcoin price (USD): ', bitcoin_price)

    except Exception as e:
        # Обработка исключений во время запроса
        print('Error during request:', e)

Этот код работает аналогично коду из предыдущего примера.

Raspberry Pi Pico MicroPython HTTP GET-запрос — курс биткоина

Развитие проекта

Теперь вы можете развить этот проект дальше и отображать курс биткоина на :doc:`OLED </raspberry/pico/raspberry-pi-pico-ssd1306-oled-micropython/index>`_ или :doc:`LCD </raspberry/pico/raspberry-pi-pico-i2c-lcd-display-micropython/index>`_ и обновлять данные каждый день. Вы также можете запрашивать данные для различных криптовалют.

Вы также можете добавить какое-либо уведомление, которое будет отправлять вам :doc:`сообщение </raspberry/pico/raspberry-pi-pico-w-send-email-micropython/index>`_, когда цена пересечет определенное пороговое значение.

Заключение

В этом руководстве вы узнали об HTTP GET-запросах и о том, почему они полезны. Мы также показали вам два разных примера получения данных из интернета.

Надеемся, это руководство было для вас полезным.