
В прошлой статье мы рассмотрели, как отлаживать код, загружать отредактированные файлы и удалять ненужные файлы на устройстве прямо из браузера (беспроводное управление устройством) через 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. Создаются при инициализации (в меню File → Init 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
Логику работы с датчиком уровня воды
Полную интеграцию с выбранной системой уведомлений
Оптимизация и работа с памятью модуля
Данный код станет рабочей основой для реального проекта — датчика уровня воды в колодце.
