Як керувати датчиками розумного будинку за допомогою Google Assistant
Російський військовий корабель, іди *****!
Привіт! У цьому посібнику розповім, як створити свій власний голосовий додаток в Google Assistant та керувати датчиками розумного будинку на прикладі плати ESP8266 та світлодіода.
На жаль, українська мова поки що не підтримується в асистенті, тому будемо використовувати англійську. Для цього нам знадобиться контролер ESP8266 або інші контролери з підключенням до інтернету і сервер з валідним ssl-сертифікатом (замість валідного ssl можна використовувати зворотний proxy, в якого такий вже є) і MQTT сервер (broker). Для інтеграції з Google assistant будемо використовувати сервіс Google Actions та Dialogflow. Тож почнемо.
Створення та налаштування проєкту
Для початку потрібно авторизуватися в Google Action Console, створити проєкт, обрати мову та регіон. Після цього потрібно вибрати сферу застосування. Я вибрав Custom. З чужого досвіду скажу, що категорія Smart Home працює коректно тільки з пристроями від Google, для коректної роботи краще обрати іншу категорію.
Далі вигадуємо як зватимуть нашого бота та обираємо голос з доступних.
Наміри
Наміри представляють завдання, для виконання яких асистент потребує відповіді/реакції користувача. Існує два основних типи намірів: системні та користувацькі.
Системні є стандартними готовими командами. Наприклад, користувач може погодитись з пропозицією асистента, сказавши «okey», «yes», «you», або асистент може зупинити відтворення, почувши «stop».
Користувацькі наміри та фрази розширюють можливість розуміння асистента. При створенні наміру ви маєте вказати такі елементи:
- Вказати, чи це глобальний намір. Позначення глобального наміру вказує, чи може асистент відповідати вказаному наміру користувача під час розмови.
- Створити навчальні фрази — це приклади того, що користувач може сказати, щоб відповідати наміру.
Параметри наміру використовуються для визначення та вилучення значень у навчальних фразах. Це конкретні слова або фрази, які ви хочете отримати від користувача.
Налаштування зворотного proxy та DNS
Для взаємодії із Actions Console потрібен SSL-сертифікат. Це значить, що ваш сайт має бути доступним через https. Цю частину можна пропустити, якщо у вас є хостинг із валідним сертифікатом.
Я не став встановлювати його на сервер, натомість я використав DNS proxy Cloudflare (безкоштовний — basic).
Для цього в кабінеті домену потрібно змінити NS, а саме додати А запис. Процедура заміни NS може зайняти до 48 годин.
Сервіс Cloudflare пропонує безліч імен нижніх рівнів, тому якщо ви маєте проблеми з виконанням наступного пункту, можливо варто вказати свою IP-адресу в колонці content біля www ***, https // www *** (де *** це ваш домен).
Встановлення програм на VPS-сервер
Для роботи додатку встановимо PHP-скрипт на VPS-сервері, який буде передавати наші дані до MQTT-брокера, а той, в свою чергу, на ESP. Деякі хостинг-провайдери надають бонусний безкоштовний період.
Приклад AWS або Digital Ocean. Насамперед, після першого запуску сервера, необхідно оновити базу даних пакетів та пакети:
apt update apt upgrade
Після встановимо Apache2:
apt install apache2
Після цього, якщо ви вставите адресу вашого сервера в рядок браузера, ви побачите стандартну сторінку Apache2.
Також встановимо PHP.
apt-get install php libapache2-mod-php
Встановлення mcrypt
Розширення mcrypt переміщено в репозиторій PECL і більше не входить у комплект PHP з PHP 7.2.0 .
PECL — це репозиторій модулів для PHP, де користувачі можуть завантажувати та розміщувати розроблені PHP-розширення.
Встановимо інструменти розробки Ubuntu:
sudo apt install -y build-essential
Встановимо PHP, dev і Pear:
sudo apt install php php-pear php-dev libmcrypt-dev
Оновимо список каналів PECL:
sudo pecl channel-update pecl.php.net sudo pecl update-channels
Встановимо mcrypt:
sudo pecl install mcrypt
Коли ви побачите підказку libmcrypt prefix? [autodetect]
, натисніть Enter для автоматичного визначення.
Встановимо БД MySQL:
apt-get install php-mysql
Встановимо бібліотеку Mosquitto для PHP:
pecl install Mosquitto-alpha
MQTT — це простий мережевий протокол, що працює на TCP/IP. Використовується для обміну повідомленнями між пристроями за принципом видавець-підписник. Оскільки протокол розуміє лише певні типи повідомлень, йому потрібен перетворювач (broker). У нашому випадку він має назву Mosquitto.
Додайте рядок extension = mosquitto.so
до файлу php.ini.
Я отримав до нього доступ за допомогою команди sudo nano /etc/php/7.4/apache2/php.ini
Встановіть клієнт:apt install mosquitto mosquitto-clients
Налаштування PHP-скрипта, підписка на topic
Призначення PHP-скрипта приймати POST-запит від Google Assistant, виймати з нього action і передавати його як повідомлення у топік брокера, назва якого вказана наприкінці скрипта. Як ви назвете скрипт, значення немає. Помістіть скрипт на своєму сервері за адресою /var/www/html
Щоб створити топік, скористайтесь командою:mosquitto_sub -h localhost - t /test/light
Замість localhost ви можете задати будь-яку іншу адресу або домен, де ви хочете створити видавця (pub).
Замість / test / light ви можете задати будь-яку тему. Головне, щоб вона була вказана у скрипті.
Повідомлення створюються видавцями. Щоб створити повідомлення, можна скористатися командою.
mosquitto_pub -h localhost - t / test / light -m " light "
Але вона нам не знадобиться, оскільки нашим видавцем (pub) буде наша програма. Схема така: коли наша програма отримує команду, вона надсилає запит на наш скрипт. Скрипт на брокера, а брокер на підписника (ESP8266).
Перевіряти надсилання повідомлень ми будемо через вкладку Test Action Console.
Скрипт PHP
<?php //Make sure that it is a POST request. if(strcasecmp($_SERVER['REQUEST_METHOD'], 'POST') != 0){ throw new Exception('Request method must be POST!'); } //Make sure that the content type of the POST request has been set to application/json $contentType = isset($_SERVER["CONTENT_TYPE"]) ? trim($_SERVER["CONTENT_TYPE"]) : ''; if(strcasecmp($contentType, 'application/json') != 0){ throw new Exception('Content type must be: application/json'); } //Receive the RAW post data. $content = trim(file_get_contents("php://input")); //Attempt to decode the incoming RAW post data from JSON. $decoded = json_decode($content); //file_put_contents($filename, $data); var_dump($decoded); echo $decoded->queryResult->action; define('BROKER', 'localhost'); define('PORT', 1883); define('CLIENT_ID', getmypid()); ити $client = new Mosquitto\Client(CLIENT_ID); $client->connect(BROKER, PORT, 60); $message = $decoded->queryResult->action; $client->publish('/test/light', $message, 0, false); $client->loop(); ?>
Webhooks
Вебхуки — це один із способів, за допомогою яких програми можуть надсилати автоматичні повідомлення або інформацію іншим програмам. Для того щоб наш скрипт працював з асистентом? переходимо у вкладку develop у верхньому меню. У бічному меню обираємо дію webhook та HTTPS endpoint. Тут потрібно вказати адресу скрипта, на який буде надсилатися POST-запит.
Прошивка ESP8266
Для прошивки використовуватимемо Arduino IDE. Якщо хтось буде встановлювати IDE вперше, не забудьте про драйвер ch340. По дефолту в arduino цієї плати немає. У Файл >>Налаштування потрібно вказати адресу додаткових плат: arduino.esp8266.com/ stable /package_esp8266com_index.json. В Інструменти >>плата >>менеджер плат потрібно встановити пакет esp8266.
У скетчі після const char * ssid ви повинні вказати назву своєї wi-fi мережі. Після const char * password її пароль. Після const char * mqtt_server вказати ip адресу свого сервера.
Скетч Arduino IDE
#include <ESP8266WiFi.h> #include <PubSubClient.h> // Update these with values suitable for your network. const char* ssid = "***"; const char* password = "********"; const char* mqtt_server = "**.**.*.*"; WiFiClient espClient; PubSubClient client(espClient); long lastMsg = 0; char msg[50]; int value = 0; int led = D5; void setup_wifi() { delay(10); // We start by connecting to a WiFi network Serial.println(); Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } randomSeed(micros()); Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); } void callback(char* topic, byte* payload, unsigned int length) { String msg=""; Serial.print("Message arrived ["); Serial.print(topic); Serial.print("] "); for (int i = 0; i < length; i++) { Serial.print((char)payload[i]); msg+=(char)payload[i]; } Serial.println(); // Switch on the LED if an 1 was received as first character // if ((char)payload[0] == '1') { if (msg == "light") { digitalWrite(led, HIGH); // Turn the LED on } else { digitalWrite(led, LOW); // Turn the LED off } } void reconnect() { // Loop until we're reconnected while (!client.connected()) { Serial.print("Attempting MQTT connection..."); // Create a random client ID String clientId = "ESP8266Client-"; clientId += String(random(0xffff), HEX); // Attempt to connect if (client.connect(clientId.c_str())) { Serial.println("connected"); // ... and resubscribe client.subscribe("/test/light"); } else { Serial.print("failed, rc="); Serial.print(client.state()); Serial.println(" try again in 5 seconds"); // Wait 5 seconds before retrying delay(5000); } } } void setup() { pinMode(led, OUTPUT); // Initialize the led pin as an output Serial.begin(115200); setup_wifi(); client.setServer(mqtt_server, 1883); client.setCallback(callback); } void loop() { if (!client.connected()) { reconnect(); } client.loop(); }
Результат
В результаті, після компіляції скетчу ми отримуємо програму, яка інтегрована в Google Assistant помічник і управляє датчиками.
Дякую за допомогу в написанні Хомечуку Владу та Карграмановій Юлії.
10 коментарів
Додати коментар Підписатись на коментаріВідписатись від коментарів