
В этой статье мы разберёмся, как подключать самодельные устройства к умному дому Яндекс с Алисой (далее - УДЯ). В качестве такого самодельного устройства у нас выступит Wi-Fi-метеостанция на ESP8266, обладающая следующими возможностями:
вывод уровня углекислого газа, температуры и влажности с датчика Sensirion SCD-30
передача данных этих данных в УДЯ через наше облако по Wi-Fi
вывод курсов криптовалют на встроенный экран
Содержание статьи:
Разработка аппаратной части устройства на ESP8266 / ESP32
Написание прошивки устройства в среде Ардуино
Создание сервиса в облаке на Python и Django для подключения устройства к УДЯ и хранения данных, выгрузки статистики
Подключение нашего проекта к УДЯ через Яндекс.Диалоги, учим Алису Яндекса работать с нашим устройством
Обсудим варианты доработок, подключение устройства к Home Assistant и т.д.
Вот что мы получим в результате:

Разработка аппаратной части устройства
Приступим к разработке самого устройства. Можно самому вытравить плату, припаять компоненты, распечатать на 3d-принтере корпус, но зачем, когда можно сильно сэкономить время и силы, взяв дешёвые готовые изделия, и "допилить" их под свои нужды? Именно таким решением в нашем случае и станут компактные Wi-Fi-метеостанции, которые можно купить на всем известном киитайском сайте и наших маркетплейсах по цене менее чем в тысячу рублей за штуку:

Все известные мне отладочные платы на ESP, продающиеся вместе с корпусом и имеющие на борту цветной экран, стоят дороже этой метеостанции, так что она - самый дешёвый вариант для разработки своих устройств.
Есть две модификации этого устройства:
SmallTV, на основе микроконтроллера ESP-12F и экрана диагональю 1.54" и разрешением 240х240 (увы, не сенсорного) с контроллером ST7789V - она как раз и стоит менее чем тысячу рублей:

2. SmallTV-Pro с отображением курсов криптовалют, на основе микроконтроллера ESP32-wroom-32 с сенсорной кнопкой для переключения режимов отображения (экран такой же, на ST7789V) - стоит в два раза дороже:

Есть ещё Ultra версия на ESP8266, но там ничего интересного, рассматривать не будем.
Разработчиком предусмотрительно выведены контакты, которые понадобятся нам для заливки своей прошивки, вот распиновка:

Заодно приведу и распиновку экрана:

Выводы GND, 3V3, TXD0 и RXD0 подключаем к выводам usb-uart конвертера, например ch340. Для перевода esp8266 в режим программирования нужно подтянуть GPIO0 к земле, далее, не отпуская, подтянуть кратковременно RST к земле, далее GPIO0 можно отпустить. Чтобы микроконтроллер вышел из режима программирования, снова кратковременно притягиваем RST к земле, при этом не трогая GPIO0.
Можно не мучиться так каждый раз при заливки прошивки, а взять, к примеру, программатор CG-Programmer (на ch340g) - он умеет автоматически переводить esp8266/esp32 в режим программирования.
Ещё упрощает жизнь вот такой зажим с Алиэкспресса:

не нужно каждый раз вынимать плату из корпуса, нацеплять штырьки для подключения к конвертеру - просто зацепил зажим за плату, и можно перепрошивать. Очень удобно :) Но у меня он приехал с Алиэкспресса уже после того, как начал дорабатывать метеостанцию, поэтому мне пришлось запаять на плату контактную гребёнку.
Ещё иногда попадаются версии SmallTV, в которых нет штырьков для прошивки:

в таких версиях на плате уже распаян CH340, что даёт возможность программировать модуль через встроенный usb-c разъём, без необходимости подключения внешнего usb/uart-конвертера
В прошлом году в продаже также появилась версия устройства с ESP32-S3 N16R8 и ch340 на борту и открытым исходным кодом (правда, по весьма невкусной цене):

Подключение датчика углекислого газа, температуры и влажности Sensirion SCD-30
Отлично, с выбором аппаратной платформы разобрались, теперь встаёт вопрос - какие данные мы будем передавать на устройства Яндекса с Алисой? Метеостанция не оборудована датчиками, она просто получает данные с погодного сайта (а также загруженные в память устройства пользователем) и выводит на экран. Непорядок, поэтому установим свой датчик для передачи данных в УДЯ. :) Таким датчиком станет датчик углекислого газа Sensirion SCD-30:

Sensirion SCD-30 - это двухлучевой NDIR CO2-датчик, принцип работы которого очень прост - молекулы углекислого газа непрозрачны для ИК с длиной волны 4.26 микрон, в то время как остальная часть газов проходит через него без препятствий. Для компенсации самонагрева измерительной камеры на плату датчика запаян датчик SHT31, и благодаря нему мы с SCD30 помимо CO2 можем считывать ещё и температуру с влажностью.
Чем полезен такой датчик? Каждый человек выделает углекислый газ, и в замкнутом помещении его может скапливаться очень много. Вы можете не понимать причину снижения трудоспособности, почему болит голова и причину сонливости, а причина - как раз в CO2 и необходимости проветрить помещение.
Концентрация CO2 измеряется в ppm ("parts per million" - "частей на миллион"). Это значение показывает, сколько частей CO2 находится в 1 миллионе частей воздуха. Вот таблица влияния CO2 на человека:

Датчик поддерживает целых три способа подключения - I2C, Modbus и PWM. Мы выберем для использования первый - I2C. На свободных пинах метеостанции I2C у меня не завёлся даже с внешними подтягивающими резисторами, поэтому пришлось использовать стандартные для I2C GPIO4 и GPIO5. А поскольку на GPIO5 "сидела" подсветка экрана, то пришлось сдуть оттуда резистор и припаять его к GPIO16.
Вот схема подключения Sensirion SCD30 к плате устройства:

Все отлично помещается в корпус метеостанции, SCD30 располагается вплотную к вентиляционным отверстиям в корпусе:

Далее остаётся только подключить usb/uart-конвертер для заливки нашей прошивки, которую мы напишем в следующем разделе нашей статьи. Если на борту платы уже имеется впаянный ch340 - задача упрощается, ничего подключать не нужно.
Подключаем для загрузки прошивки наше устройство к ПК на примере usb/uart-конвертера CH340G:

Как переводить ESP в режим программирования - я писал в начале статьи.
Подключение к CG-Programmer (переводит автоматически ESP в режим программирования):

Вот схема того, что получилось:

Написание прошивки для Ардуино для работы с Sensirion SCD30 и УДЯ, выводом курсов криптовалют на экран
С аппаратной частью разобрались, теперь напишем прошивку в среде Ардуино, реализующую следующую функциональность:
Получение уровня углекислого газа, температуры и влажности с датчика Sensirion SCD30
Получение курсов криптовалют на примере биткоина с coinbase.com
Получение данных о погоде с openweathermap.org
Синхронизация времени с pool.ntp.org
Отправки данных в УДЯ (умный дом Яндекса с Алисой) через наше облако
Отрисовка на экране данных с датчика и курса с использованием Adafruit ST7789
Скетч для загрузки в наше устройство можно скачать с моего гитхаба: https://github.com/tzirulnicov/smalltv_yandex Разберём его вкратце:
#define TFT_BL 16
#define TFT_DC 0
#define TFT_RST 2
#define TFT_CS -1
#define DISABLE_BACKLIGHT 1
#define ENABLE_BACKLIGHT 0
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);
настраиваем библиотеку Adafruit ST7789, указывая, к каким контактам подключён экран, и определяем константы для включения/выключения экрана
const char* ssid = "WIFI_SSID";
const char* password = "WIFI_PASSWORD";
прописываем название Wi-Fi-сети, к которой подключаться, и пароль.Тут стоит помнить, что ESP работает с Wi-Fi только на 2.4ГГц. Если роутер раздает интернет на 5ГГц, то работать не будет. Если все равно не удается подключиться к роутеру - стоит поменять тип шифрования в его настройках.
static const char* ntpServerName = "
pool.ntp.org
";
const int timeZone = 3;
прописываем NTP-сервер для синхронизации времени и задаём часовой пояс. Для Москвы это UTC+3.
String api_key = "OPENWEATHER_API_KEY";
String latitude = "55.785377";
String longitude = "37.475994";
String units = "metric";
String language = "ru";
OW_Weather ow;
Как и в оригинальной прошивке для метеостанций SmallTV, мы получаем текущую погоду с сервера openweathermap.org. Для использования его API нам необходимо зарегистрироваться на этом ресурсе и получить API-ключ, с которым наше устройство будет общаться с погодным сервисом. Бесплатный тарифный план предусматривает ограничения на количество запросов, с которыми можно ознакомиться здесь: https://openweathermap.org/price
Далее в переменных latitude и longitude мы задаём координаты места, для которого хотим получить погоду. В нашем случае это - Москва. Температуру мы хотим получать в цельсиях, поэтому указываем метрическую систему (units="metric"). Погоду хотим получить на русском языке, поэтому переменной language присваиваем значение "ru".
const char *bitcoinApiUrl = "
https://api.coinbase.com/v2/prices/BTC-RUB/sell
";
Наше устройство умеет отображать курсы криптовалют, используя API сервиса coinbase.com. Для примера на экран выводится курс продажи биткоина в рубля
х.
String serverName = "
https://nonexistentdomain.ru/yandex_smarthome/sensors_data
";
здесь мы указываем URL нашего сервиса, который мы напишем в следующем разделе нашей статьи. Поэтому адресу будут отправляться данные с датчика SCD30 и далее отправляться в УДЯ.
tft.setFont(&TimesNRCyr10pt8b);
наше устройство выводит всё на русском языке, что по умолчанию не поддерживается используемой нами графической библиотекой Adafruit GFX. Для решения этой проблемы взяты русские шрифты отсюда: https://github.com/immortalserg/AdafruitGFXRusFonts
Загрузка скетча в нашу метеостанцию
Для заливки скетча в устройство нам вначале необходимо скачать среду Ардуино с https://www.arduino.cc/en/software , установить драйвер используемого usb/uart-конвертера (если автоматом не подтянулся).
Запускаем Ардуино, открываем через Файл-Параметры окно параметров, в поле "Дополнительные ссылки для Менеджера плат" указываем "http://arduino.esp8266.com/stable/package_esp8266com_index.json,https://dl.espressif.com/dl/package_esp32_index.json".
Далее выбираем в Инструменты-Плата:
esp8266 -> Generic ESP8266 Module (в случае метеостанции с esp-12f)
esp32 -> ESP32 Dev Module (в случае метеостанции с esp32)
Далее выбираем Инструменты-Порт-порт, в которому подключена метеостанция
Устанавливаем необходимые библиотеки через Инструменты-Управление библиотеками: NTPClient, Adafruit_ST7789, ArduinoJson, OpenWeather, Sensirion I2C SCD30, Adafruit GFX Library, Time, ArduinoHTTPClient, ArduinoBearSSL.
Скачиваем с гитхаба https://github.com/tzirulnicov/smalltv_yandex скетч и открываем его, выбираем Скетч-Загрузить на плату - начнётся сборка прошивки и загрузка её на плату. После перезагрузки устройства получаем результат:

Подключение нашего устройства к УДЯ
Какие существуют способы подключения устройств к УДЯ? Их три:
своё облако (устройство общается с УДЯ через него)
ZigBee
Wi-Fi Matter
ZigBee и Wi-Fi Matter хороши тем, что при пропадании подключения к Интернет устройства Яндекса не теряют связь с подключенными к ним устройствами. Wi-Fi Matter требует наличие роутера, плюс ZigBee же - энергоэффективность, устройства с данной технологией могут работать несколько лет, питаясь от одной батарейки.
Мы же в этой статье рассмотрим первый вариант - с облаком - наше устройство будет скидывать данные на сайт в облаке (на основе фреймворка Django), а оттуда уже они будут раскатываться на устройства Яндекса. Наш web-сервис в дальнейшем можно будет доработать, отображая статистику изменения данных с устройства за заданный период (в УДЯ статистика отображается лишь за короткий период).
Написание web-сервиса для хранения данных в облаке
Теперь напишем web-сервис, который будет получать данные с нашего устройства и далее отправлять их в УДЯ. Писать будем на Питоне с использованием фреймворка Django, хранить данные - в MySQL.
Качаем проект с гитхаба: https://github.com/tzirulnicov/smalltv_yandex/tree/main/django_web_service
Создаём в MySQL таблицу для хранения данных с датчика SCD30 (СО2, температура, влажность):
CREATE TABLE sensors (
id int unsigned NOT NULL AUTO_INCREMENT,
date datetime DEFAULT CURRENT_TIMESTAMP,
scd30_temp double(3,1) DEFAULT NULL,
scd30_co2 smallint unsigned DEFAULT NULL,
scd30_h smallint DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB
Прописываем настройки в settings.py:
ALLOWED_HOSTS = ['
nonexistentdomain.ru
']
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'mysql_db_name',
'USER':'mysql_user',
'PASSWORD':'mysql_password',
'HOST':'localhost
',
'PORT':'3306'
}
}
nonexistentdomain.ru заменяем на свой домен, прописываем настройки подключения к своей БД.
yandex_smarthome/urls.py:
urlpatterns = [
path('sensors_data', views.sensors_data),
path('oauth/login', views.oauth_login),
path('token', views.oauth_token),
path('v1.0/user/devices', views.user_devices),
path('v1.0/user/devices/query', views.user_devices_query),
path('refresh', views.refresh)
]
в файле роутинга приложения yandex_smarthome прописаны адреса для получения данных с нашей метеостанции ( /yandex_smarthome/sensors_data ) и отправки данных в УДЯ (авторизация через OAuth, выдача данных датчика). Код в views.py максимально упрощён, поэтому используются константы вроде "1234". Выкатывать такое в продакшн точно не стоит, но для ознакомления с работой с УДЯ сгодится. :)
Подключение нашего проекта к УДЯ
Наконец-то у нас всё готово для подключения нашего проекта к умному дому Яндекса, пора научить Алису работе с нашим устройством. Для подключения будем использовать платформу Яндекс.Диалогов. Как это сделать - описано в документации: https://yandex.ru/dev/dialogs/smart-home/doc/ru/
Основные этапы:

Открываем https://dialogs.yandex.ru/developer/ , выбираем "Создать диалог", далее "Умный дом", после чего откроется страница "Новый умный дом". В разделе "Настройки" открывшейся страницы вводим:

не забываем поменять nonexistent.ru на свой домен, куда будет "стучаться" УДЯ. Перед сохранением понадобится подтвердить права на этот домен через Яндекс.Вебмастер любым из удобных способов - размещение html-файла, метатега на главной странице, либо записью в DNS.
После сохранения введённых настроек переходим во вкладку "Связка аккаунтов" и задаём настройки уже там:

по этим адресам УДЯ будет взаимодействовать с нашим web-сервисом для получения данных с датчика метеостанции. Есть ограничения - наш сервис должен отвечать не дольше 3 секунд. длина ответа - до 5000 символов (oauth и refresh-токенов - до 2048 символов), подробнее здесь.
Здесь требуется указать идентификатор приложения и его секрет. Чтобы их получить, заходим на https://oauth.yandex.ru/ , нажимаем "Создать приложение", вводим произвольное название, ставим галку "Веб-сервисы", Redirect URI - свой домен. Далее заходим в "Мои приложения" и Client ID c Client secret оттуда копируем в "Идентификатор приложения" и "Секрет приложения" платформы Диалогов (см. скриншот выше).
Далее открываем вкладку "Тестирование", где мы можем протестировать созданную связку с УДЯ:

Отправлять навык на модерацию и публиковать его нет необходимости - после тестирования он станет доступен в приложении УДЯ, приложениях Яндекса с Алисой (Яндекс.Навигаторе и т.д.), с ним начнут работать привязанные к аккаунту Яндекс.Станции, телевизоры и другие устройства Яндекса с Алисой (см. видеоролик и скриншоты в начале статьи).
Можно настроить сценарии автоматизации в приложении "Дом с Алисой" - например, при каких значениях с нашей метеостанции включать/выключать кондиционер в квартире.
Мы создали простой каркас нашего проекта, обладающий базовой функциональностью. Возможные варианты доработок:
нарисовать красивый интерфейс для вывода на экран устройства с использованием библиотеки LVGL в Eez Studio / SquareLine Studio (пример работы с LVGL выложен по ссылкам ниже)
для переключения экранных режимов подключить сенсорную кнопку на TP223 в случае ESP8266 (в случае ESP32 - у микроконтроллера имеется встроенный сенсорный интерфейс, металлический пятак припаивается сразу к ножке микроконтроллера)
Подключить датчик качества воздуха Sensirion SGP30 (шина I2C), датчик присутствия LD2410C и т.д. - размеры корпуса это позволяют
Доработать web-сервис для отображения статистики изменения данных с устройства, которые у нас сохраняются в таблице sensors (для чего мы уже сохраняем время их отправки).
Все ограничено лишь вашей фантазией и желаниями. :)
Ссылки на материалы по теме
Исходники проекта этой статьи: https://github.com/tzirulnicov/smalltv_yandex
Использование метеостанций SmallTV для установки ESPHome и подключения к Home Assistant
Исходный код проекта метеостанции HoloCubic - думаю, разработчик устройств SmallTV взял за основу именно этот проект
Исходный код проекта GeekMagic S3 - для метеостанций с ESP32-S3 N16R8
Пример с LVGL для ESP-IDF для метеостанций SmallTV
Работа с датчиком Sensirion SCD-30
Русские шрифты для библиотеки Adafruit GFX