В прошлой статье  мы рассмотрели, как отлаживать код, загружать отредактированные файлы и удалять ненужные файлы на устройстве прямо из браузера (беспроводное управление устройством) через WebREPL и через uPyLoader. Теперь научим устройство "говорить" — отправлять нам сообщения  через систему push-уведомлений популярных мессенджеров.

Для сохранения логической целостности цикла статей я включил этот раздел, даже учитывая наличие похожих материалов на Хабре. Цель — не просто повторить известную информацию, а показать проверенные решения, адаптированные под конкретный проект и решающие проблему с русской кодировкой и эмодзи.

Мы протестируем две системы уведомлений:

Telegram-бот — для ESP32, который будет отображать сообщения от модуля, обладающего достаточными ресурсами  для обработки SSL-шифрования, требуемого Telegram API.

  ntfy — легковесное решение для отображения сообщений для ESP8266, не требующее ресурсоемкого шифрования и идеально подходящее для устройств с ограниченной памятью.

 Вы сможете выбрать подходящий вариант для своего проекта.

 Чем конкретно займемся?

 Созданием Telegram-бота через @BotFather с запуском тестового кода для отправки сообщений в созданный Telegram-бот.

Настройкой ntfy-каналов с запуском тестового кода на ESP8266 для отправки сообщений в топик ntfy.

Создание Telegram бота, получение Токена и Chat ID

Шаг 1: Создаем бота через @BotFather, получаем Токен.

Откройте Telegram и найдите @BotFather (официальный бот для создания ботов)

 Отправьте команду: /newbot

Введите имя бота (то, что будут видеть пользователи), например: My ESP32 Assistant

Введите username бота (должен заканчиваться на bot), например: my_esp32_bot

Сохраните Токен который выдаст BotFather.

Шаг 2: Получаем Chat ID

 Через специального бота - @userinfobot. Отправьте любую команду, например  /help. Сохраните 10-ти значный  id (пример Id: 5207544788)

 Соблюдайте правила безопасности: НИКОМУ не показывайте Токен — это пароль от вашего бота, не публикуйте Токен в открытом доступе (GitHub, форумы и т.д.).

 Документация по Телеграмм боту. 

Настройка ESP32: создание файлов через  uPyLoader

Предлагаю для ознакомления и тестирования следующую структуру файлов:

 upload.py и  download.py служебные для загрузки и скачивания файлов в uPyLoader. Создаются при инициализации (в меню FileInit transfer files)

 boot.py        → Автозапуск WiFi

config.py      → Настройки (пароли, токены) 

test_send.py   → Тест ОТПРАВКИ в Telegram

 В прошлой статье я описал способ создания файлов через редактор кода uPyLoader.

Кратко напомню:

1. Запустите uPyLoader

2. Подключитесь к ESP32 (Connection → Connect)

3. Откройте редактор: View → Code Editor

СОЗДАНИЕ КОНФИГУРАЦИОННОГО ФАЙЛА

 В поле MCU введите: config.py

Код для нижнего окна:

# НАСТРОЙКИ WiFi
WIFI_SSID = "your_wifi_name"          # Имя вашей WiFi сети
WIFI_PASSWORD = "your_wifi_password"  # Пароль от WiFi, если ваш пароль состоит из цифр то, не лишним будет оформить его в бинарный режим пример b”12345678”
# НАСТРОЙКИ TELEGRAM БОТА
TELEGRAM_TOKEN = "1234467890:ABCdefGHIjklMNOpqrsTUVwxyz"  # Ваш Токен бота
TELEGRAM_CHAT_ID = 123456789  # Ваш Chat ID

Нажмите → Save

СОЗДАНИЕ ФАЙЛА ПОДКЛЮЧЕНИЯ WiFi

 В поле MCU введите: boot.py

Код для нижнего окна:

import network # Работа с WiFi
import time # Паузы и задержки
from config import WIFI_SSID, WIFI_PASSWORD

# Основная функция подключения к wifi
def connect_wifi():
    wlan = network.WLAN(network.STA_IF)  # подключение к WiFi в режиме клиента
    wlan.active(True) # включение WiFi-модуля ESP
    
    # Проверяем статус подключения
    if wlan.isconnected():
        print(f"WiFi уже подключен: {wlan.ifconfig()[0]}")
        return True
    else:
        # Если не подключен - подключаемся
        print(f" Подключаемся к {WIFI_SSID}...")
        wlan.connect(WIFI_SSID, WIFI_PASSWORD)
        
        # Ожидание и проверка подключения
        for i in range(10):
            if wlan.isconnected():
                print(f" WiFi подключен! IP: {wlan.ifconfig()[0]}")
                return True
            time.sleep(1)
        
        print(" Не удалось подключиться к WiFi")
        return False

# Автозапуск
connect_wifi()

Нажмите → Save

Функция подключения к WiFi выполняет следующие шаги: инициализация клиентского режима, активация WiFi-модуля, проверка текущего статуса подключения, установка соединения при необходимости, ожидание подтверждения подключения и финальная отчетность о результате.

ЗАПУСК ТЕСТА

1. Закройте редактор кода

2. В главном окне выберите файл boot.py

3. Нажмите → Execute

СОЗДАНИЕ ТЕСТОВОГО ФАЙЛА ДЛЯ ОТПРАВКИ

 В поле MCU введите: test_send.py

Код для нижнего окна:

import urequests     # для отправки запросов
import time
import gc     # Чистка памяти
from config import TELEGRAM_TOKEN, TELEGRAM_CHAT_ID 

def send_telegram_message(text): 
    """Основная функция отправки сообщения в Telegram""" 
    # Очищаем память перед выполнением запроса
    gc.collect()
    
    # Формируем URL для запроса к Telegram API
    url = f"https://api.telegram.org/bot{TELEGRAM_TOKEN}/sendMessage?chat_id={TELEGRAM_CHAT_ID}&text={text}" 
    
    try: 
        # Отправляем GET-запрос к серверу Telegram
        response = urequests.get(url)
        
        # Проверяем статус ответа сервера
        if response.status_code == 200:
            result = True
            print(f" Сообщение отправлено: '{text}'")
        else:
            result = False
            print(f" Ошибка HTTP {response.status_code}: '{text}'")
        
        # Закрываем соединение для освобождения ресурсов
        response.close()
        return result
        
    except Exception as e: 
        # Обрабатываем ошибки соединения
        print(f" Ошибка соединения: {e}")
        return False 
    
    finally:
        # Гарантированно очищаем память после выполнения запроса
        gc.collect()

# ТЕСТИРОВАНИЕ функции, запускается при выполнении файла

messages = [ 
    " ESP32 успешно запущен!", 
    "? Тестируем отправку сообщений", 
    "? Русский текст работает.", 
    "? Эмодзи тоже! ?❤️?" 
] 

for i, msg in enumerate(messages, 1):
    print(f"\n Тест {i}/4") 
    success = send_telegram_message(msg) 
    
    if not success:
        print(" Останавливаем тест из-за ошибки")
        break
    
    time.sleep(3)

print(" ТЕСТИРОВАНИЕ ЗАВЕРШЕНО!")

Нажмите → Save

Функция send_telegram_message(text) выполняет следующие шаги:

Очистка оперативной памяти перед выполнением запроса

Формирование URL для API Telegram с токеном бота, ID чата и текстом сообщения.

Отправка GET-запроса к серверу Telegram.

Проверка статуса ответа - успешным считается только код 200.

Логирование результата в терминал.

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

Очистка памяти после выполнения запроса.

Возврат результата (True/False) для дальнейшей обработки.

Обработка ошибок: перехват исключений при проблемах с соединением, логирование ошибок с понятными сообщениями.

Гарантированная очистка памяти даже при сбоях.

Если коротко:"Очистили память, отправили сообщение в Telegram, проверили ответ, почистили за собой и сообщили о результате"

 ЗАПУСК ТЕСТА

1. Закройте редактор кода

2. В главном окне выберите файл test_send.py

3. Нажмите → Execute

4. Посмотрите результат в Телеграмм боте

Вот так выглядят мои сообщения от датчика воды:

Telegram Bot API имеет особенность - он позволяет использовать GET-запросы для отправки данных. Хотя технически GET предназначен для получения данных, в случае Telegram это работает и упрощает код для микроконтроллеров и позволяет работать с русским текстом и эмодзи.

Ниже приведен POST-запрос, где приходиться вручную кодировать текст в UTF-8 и формировать тело запроса в бинарном виде, чтобы можно было работать с русским текстом и эмодзи:

Скрытый текст
def send_telegram(text):
    """ POST-запрос в Telegram бот"""
    # Формируем URL для API Telegram
    url = "https://api.telegram.org/bot" + TELEGRAM_TOKEN + "/sendMessage"
    
    # Собираем тело запроса вручную, кодируя каждую часть:
    # - chat_id преобразуем в строку и затем в байты
    # - текст сообщения кодируем в UTF-8 для поддержки русского и эмодзи
    # - собираем все части в бинарном формате для надежной передачи
    body = b"chat_id=" + str(TELEGRAM_CHAT_ID).encode() + b"&text=" + text.encode('utf-8')
    
    # Указываем тип содержимого - форма данных веб-форм
    headers = {'Content-Type': 'application/x-www-form-urlencoded'}
    # Отправляем POST-запрос и проверяем успешность по статусу 200
    return urequests.post(url, data=body, headers=headers).status_code == 200

Настройкой ntfy-каналов с запуском тестового кода на ESP8266 для отправки сообщений в топик ntfy.

Особенности ntfy:

HTTP вместо HTTPS - не требует шифрования

POST-запросы - стандартный подход для отправки данных

Не требует регистрации - просто укажите topic

Легковесный - идеально для ESP8266

 Что понадобится?

Телефон со скаченным приложением ntfy и модуль ESP8266 (NodeMCU, Wemos D1 или др.)

Документация по ntfy

Шаг 1: Установите приложение ntfy

Скачайте ntfy из App Store или Google Play.

Откройте приложение и нажмите "+"

Создайте уникальное имя топика, например: my_esp8266_alerts, нажмите ПОДПИСАТЬСЯ

Настройка ESP8266: создание файлов через  uPyLoader

 Структура файлов:

 upload.py и  download.py служебные для загрузки и скачивания файлов в uPyLoader.

boot.py        → Автозапуск WiFi

config.py      → Настройки (пароли) 

test_send_ntfy.py   → Тест ОТПРАВКИ в NTFY

СОЗДАНИЕ КОНФИГУРАЦИОННОГО ФАЙЛА

 В поле MCU введите: config.py

Код для нижнего окна:

# НАСТРОЙКИ WiFi
WIFI_SSID = "your_wifi_name"          # Имя вашей WiFi сети
WIFI_PASSWORD = "your_wifi_password"  # Пароль от WiFi, если ваш пароль состоит из цифр то, не лишним будет оформить его в бинарный режим пример b”12345678”

Нажмите → Save

СОЗДАНИЕ ФАЙЛА ПОДКЛЮЧЕНИЯ WiFi – тоже самое, что и для Телеграмм бота

Скрытый текст
import network # Работа с WiFi
import time # Паузы и задержки
from config import WIFI_SSID, WIFI_PASSWORD

# Основная функция подключения к wifi
def connect_wifi():
    wlan = network.WLAN(network.STA_IF)  # подключение к WiFi в режиме клиента
    wlan.active(True) # включение WiFi-модуля ESP
    
    # Проверяем статус подключения
    if wlan.isconnected():
        print(f"WiFi уже подключен: {wlan.ifconfig()[0]}")
        return True
    else:
        # Если не подключен - подключаемся
        print(f" Подключаемся к {WIFI_SSID}...")
        wlan.connect(WIFI_SSID, WIFI_PASSWORD)
        
        # Ожидание и проверка подключения
        for i in range(10):
            if wlan.isconnected():
                print(f" WiFi подключен! IP: {wlan.ifconfig()[0]}")
                return True
            time.sleep(1)
        
        print(" Не удалось подключиться к WiFi")
        return False

# Автозапуск
connect_wifi()

Нажмите → Save

СОЗДАНИЕ ТЕСТОВОГО ФАЙЛА ДЛЯ ОТПРАВКИ

 В поле MCU введите: test_send_ntfy.py

Код для нижнего окна:

import urequests
import time
import gc

def send_ntfy_message(text, topic="my_esp8266_alerts"):# УКАЗЫВАЕМ ИМЯ СВОЕГО ТОПИКА
    """Основная функция отправки сообщения в ntfy"""
    # Очищаем память перед выполнением запроса
    gc.collect()
    
    # Формируем URL для запроса к ntfy
    url = f"http://ntfy.sh/{topic}"
    
    try: 
        # ОТПРАВЛЯЕМ КАК В ДОКУМЕНТАЦИИ: данные в теле с UTF-8 кодировкой
        response = urequests.post(url, data=text.encode('utf-8'))
        
        # Проверяем статус ответа сервера
        if response.status_code == 200:
            result = True
            print(f"Сообщение отправлено: '{text}'")
        else:
            result = False
            print(f"Ошибка HTTP {response.status_code}: '{text}'")
        
        # Закрываем соединение для освобождения ресурсов
        response.close()
        return result
        
    except Exception as e: 
        # Обрабатываем ошибки соединения
        print(f" Ошибка соединения: {e}")
        return False 
    
    finally:
        # Гарантированно очищаем память после выполнения запроса
        gc.collect()

# ТЕСТИРОВАНИЕ функции, запускается при выполнении файла
messages = [ 
    "? ESP32 успешно запущен!", 
    "? Тестируем отправку сообщений", 
    "? Русский текст работает!", 
    "? Эмодзи тоже! ?❤️?" 
] 

for i, msg in enumerate(messages, 1):
    print(f"\n Тест {i}/4") 
    success = send_ntfy_message(msg) 
    
    if not success:
        print("Останавливаем тест из-за ошибки")
        break
    
    time.sleep(3)

print(" ТЕСТИРОВАНИЕ ntfy ЗАВЕРШЕНО!")

Topic можно изменить в вызове функции: send_ntfy_message("Сообщение", "my_custom_topic").

Возможные проблемы и решения

 Для Telegram:

- "Сообщения не приходят" → Проверьте токен и Chat ID, убедитесь что бот активен

- "Ошибка памяти" → В коде уже используется gc.collect(), но при расширении проекта следите за использованием памяти

- "Не работает русский текст" → В GET-запросе проблем быть не должно, в POST нужна кодировка UTF-8

 Для ntfy:

- "Сообщения не приходят" → Проверьте точное имя топика

- "Ошибка подключения" → Проверьте WiFi соединение

Подводя итог тестированию, то видно что ESP32 'тянет' защищенный HTTPS для Telegram, а ESP8266 довольствуется быстрым HTTP в ntfy, но оба решения отлично работают с русским языком и эмодзи!

В следующей статье объединим знания из предыдущих материалов и создадим законченный код системы мониторинга, включающий:

 Подключение через WebREPL для удаленного управления

Автоматическое соединение с Wi-Fi

Логику работы с датчиком уровня воды

Полную интеграцию с выбранной системой уведомлений

Оптимизация и работа с памятью модуля

Данный код станет рабочей основой для реального проекта — датчика уровня воды в колодце.

Комментарии (1)


  1. Jury_78
    03.11.2025 08:02

    вручную кодировать текст в UTF-8

    Насколько я помню в micropython строки по умолчанию в utf8.