1. Прежде чем начать
Как разработчик Интернета вещей (IoT), вы можете создавать интеграцию между облаками , которая дает вашим пользователям возможность управлять своими устройствами с помощью сенсорного управления в приложении Google Home и голосовых команд с помощью Ассистента.
Интеграция между облаком основана на использовании Home Graph для предоставления контекстных данных о доме и его устройствах, создавая логическую карту дома. Этот контекст дает Помощнику более естественное понимание запросов пользователя относительно его местоположения в доме. Например, Home Graph может хранить концепцию гостиной, в которой есть несколько типов устройств разных производителей, таких как термостат, лампа, вентилятор и пылесос.
Предварительные условия
Что ты построишь
В этой лаборатории кода вы опубликуете облачную службу, которая управляет виртуальной интеллектуальной стиральной машиной, затем создадите интеграцию между облаками и подключите ее к Помощнику.
Что вы узнаете
- Как развернуть облачный сервис умного дома
- Как подключить свой сервис к Ассистенту
- Как опубликовать изменения состояния устройства в Google
Что вам понадобится
- Веб-браузер, например Google Chrome.
- Устройство iOS или Android с установленным приложением Google Home.
- Node.js версии 10.16 или новее
- Платежный аккаунт Google Cloud
2. Начало работы
Включить контроль активности
Чтобы использовать Google Assistant, вы должны предоставить Google определенные данные о деятельности. Google Assistant нужны эти данные для правильной работы; однако требование обмена данными не является специфичным для SDK. Чтобы поделиться этими данными, создайте учетную запись Google , если у вас ее еще нет. Вы можете использовать любую учетную запись Google — это не обязательно должна быть ваша учетная запись разработчика.
Откройте страницу «Контроль активности» для учетной записи Google, которую вы хотите использовать с Ассистентом.
Убедитесь, что следующие тумблеры включены:
- Активность в Интернете и приложениях . Кроме того, обязательно установите флажок Включать историю и активность Chrome на сайтах, приложениях и устройствах, использующих службы Google .
- Информация об устройстве
- Голосовая и аудио активность
Создайте проект интеграции облака в облако.
- Перейдите в консоль разработчика .
- Нажмите «Создать проект» , введите имя проекта и нажмите «Создать проект» .
Выберите интеграцию «облако-облако».
На главной странице проекта в консоли разработчика выберите Добавить интеграцию «облако-облако» в разделе «Облако-облако» .
Установите интерфейс командной строки Firebase
Интерфейс командной строки Firebase (CLI) позволит вам обслуживать ваши веб-приложения локально и развертывать их на хостинге Firebase.
Чтобы установить CLI, выполните следующую команду npm из терминала:
npm install -g firebase-tools
Чтобы убедиться, что CLI установлен правильно, запустите:
firebase --version
Авторизуйте Firebase CLI с помощью своей учетной записи Google, выполнив:
firebase login
3. Запустите стартовое приложение.
Теперь, когда вы настроили среду разработки, вы можете развернуть стартовый проект, чтобы убедиться, что все настроено правильно.
Получить исходный код
Щелкните следующую ссылку, чтобы загрузить образец этой лаборатории кода на свою машину разработки:
Вы также можете клонировать репозиторий GitHub из командной строки:
git clone https://github.com/google-home/smarthome-washer.git
О проекте
Стартовый проект содержит следующие подкаталоги:
-
public:
интерфейсный интерфейс, позволяющий легко управлять и отслеживать состояние умной стиральной машины. -
functions:
полностью реализованный облачный сервис, который управляет интеллектуальной стиральной машиной с помощью облачных функций для Firebase и базы данных Firebase Realtime.
Создать проект Firebase
- Перейдите в Firebase .
- Нажмите «Создать проект» и введите имя проекта.
- Установите флажок «Соглашение» и нажмите «Продолжить» . Если флажок «Соглашение» отсутствует, вы можете пропустить этот шаг.
- После создания проекта Firebase найдите идентификатор проекта. Перейдите в раздел «Обзор проекта» и щелкните значок настроек > «Настройки проекта» .
- Ваш проект указан на вкладке «Общие» .
Подключиться к Firebase
Перейдите в каталог washer-start
, затем настройте Firebase CLI для вашего проекта интеграции:
cd washer-start firebase use <firebase-project-id>
Настроить проект Firebase
Инициализируйте проект Firebase.
firebase init
Выберите функции CLI, базу данных реального времени , функции и функцию хостинга , включающую хостинг Firebase.
? Which Firebase CLI features do you want to set up for this directory? Press Space to select features, then Enter to confirm your choices. ❯◉ Realtime Database: Configure a security rules file for Realtime Database and (optionally) provision default instance ◯ Firestore: Configure security rules and indexes files for Firestore ◉ Functions: Configure a Cloud Functions directory and its files ◉ Hosting: Configure files for Firebase Hosting and (optionally) set up GitHub Action deploys ◯ Hosting: Set up GitHub Action deploys ◯ Storage: Configure a security rules file for Cloud Storage ◯ Emulators: Set up local emulators for Firebase products ◯ Remote Config: Configure a template file for Remote Config ◯ Extensions: Set up an empty Extensions manifest
Это инициализирует необходимые API и функции для вашего проекта.
При появлении запроса инициализируйте базу данных реального времени. Вы можете использовать расположение по умолчанию для экземпляра базы данных.
? It seems like you haven't initialized Realtime Database in your project yet. Do you want to set it up? Yes ? Please choose the location for your default Realtime Database instance: us-central1
Поскольку вы используете код начального проекта, выберите файл по умолчанию для правил безопасности и убедитесь, что вы не перезаписываете существующий файл правил базы данных.
? File database.rules.json already exists. Do you want to overwrite it with the Realtime Database Security Rules for <project-ID>-default-rtdb from the Firebase Console? No
Если вы повторно инициализируете свой проект, выберите «Перезаписать», когда вас спросят, хотите ли вы инициализировать или перезаписать базу кода.
? Would you like to initialize a new codebase, or overwrite an existing one? Overwrite
При настройке функций вам следует использовать файлы по умолчанию и убедиться, что вы не перезаписываете существующие файлы index.js и package.json в образце проекта.
? What language would you like to use to write Cloud Functions? JavaScript ? Do you want to use ESLint to catch probable bugs and enforce style? No ? File functions/package.json already exists. Overwrite? No ? File functions/index.js already exists. Overwrite? No
Если вы повторно инициализируете свой проект, выберите «Нет» , когда вас спросят, хотите ли вы инициализировать или перезаписать function/.gitignore.
? File functions/.gitignore already exists. Overwrite? No
? Do you want to install dependencies with npm now? Yes
Наконец, настройте хостинг на использование public
каталога в коде проекта и используйте существующий файл index.html . Выберите Нет, когда вас попросят использовать ESLint.
? What do you want to use as your public directory? public ? Configure as a single-page app (rewrite all urls to /index.html)? Yes ? Set up automatic builds and deploys with GitHub? No ? File public/index.html already exists. Overwrite? No
Если ESLint был случайно включен, его можно отключить двумя способами:
- Используя графический интерфейс, перейдите в папку
../functions
проекта, выберите скрытый файл.eslintrc.js
и удалите его. Не путайте его с аналогичным именем.eslintrc.json
. - Используя командную строку:
cd functions rm .eslintrc.js
В файле washer-done/firebase.json
дополните код:
{
"database": {
"rules": "database.rules.json"
},
"hosting": {
"public": "public",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
},
"headers": [{
"source" : "**/*.@(js|html)",
"headers" : [ {
"key" : "Cache-Control",
"value" : "max-age=0"
} ]
}],
"functions": [
{
"source": "functions",
"codebase": "default",
"ignore": [
"node_modules",
".git",
"firebase-debug.log",
"firebase-debug.*.log",
"*.local"
]
}
]
}
Развертывание в Firebase
Теперь, когда вы установили зависимости и настроили свой проект, вы готовы запустить приложение в первый раз.
firebase deploy
Это вывод консоли, который вы должны увидеть:
... ✔ Deploy complete! Project Console: https://console.firebase.google.com/project/<firebase-project-id>/overview Hosting URL: https://<firebase-project-id>.web.app
Эта команда развертывает веб-приложение вместе с несколькими облачными функциями для Firebase .
Откройте URL-адрес хостинга в браузере ( https:// .web.app
https:// .web.app
) для просмотра веб-приложения. Вы увидите следующий интерфейс:
Этот веб-интерфейс представляет собой стороннюю платформу для просмотра или изменения состояний устройства. Чтобы начать заполнять базу данных информацией об устройстве, нажмите «ОБНОВИТЬ» . На странице вы не увидите никаких изменений, но текущее состояние вашей стиральной машины будет сохранено в базе данных.
Теперь пришло время подключить развернутый вами облачный сервис к Google Assistant с помощью консоли разработчика Google Home .
Настройте проект консоли разработчика
На вкладке «Разработка» добавьте отображаемое имя для вашего взаимодействия. Это имя появится в приложении Google Home.
В разделе «Фирменный стиль приложения» загрузите png
файл значка приложения размером 144 x 144 пикселей с именем.png
.
Чтобы включить привязку учетной записи, используйте следующие настройки привязки учетной записи:
Идентификатор клиента | |
Секрет клиента | |
URL-адрес авторизации | |
URL-адрес токена | |
В разделе «URL-адрес выполнения облака» введите URL-адрес вашей облачной функции, которая обеспечивает выполнение намерений «умного дома».
https://us-central1- -cloudfunctions.net/smarthome
https://us-central1- -cloudfunctions.net/smarthome
Нажмите «Сохранить» , чтобы сохранить конфигурацию проекта, затем нажмите «Далее: Тест», чтобы включить тестирование вашего проекта.
Теперь вы можете приступить к реализации веб-перехватчиков, необходимых для связи состояния устройства с Ассистентом.
4. Создайте шайбу
Теперь, когда вы настроили интеграцию, вы можете добавлять устройства и отправлять данные. Ваша облачная служба должна обрабатывать следующие цели:
- Намерение
SYNC
возникает, когда Ассистент хочет знать, какие устройства подключил пользователь. Он отправляется в вашу службу, когда пользователь связывает учетную запись. Вы должны ответить, отправив в формате JSON данные обо всех устройствах пользователя и их возможностях. - Намерение
QUERY
возникает, когда Ассистент хочет узнать текущее состояние или статус устройства. Вы должны ответить с помощью полезных данных JSON с состоянием каждого запрошенного устройства. - Намерение
EXECUTE
возникает, когда Помощник хочет управлять устройством от имени пользователя. Вы должны ответить с помощью полезных данных JSON со статусом выполнения каждого запрошенного устройства. - Намерение
DISCONNECT
возникает, когда пользователь отключает связь своей учетной записи с Ассистентом. Вам следует прекратить отправлять события для устройств этого пользователя в Ассистент.
В следующих разделах вы обновите функции, которые вы ранее развернули для обработки этих намерений.
Обновить ответ SYNC
Откройте functions/index.js
, который содержит код для ответа на запросы Ассистента.
Вам нужно будет обработать намерение SYNC
, вернув метаданные и возможности устройства. Обновите JSON в массиве onSync
, включив в него информацию об устройстве и рекомендуемые характеристики стиральной машины.
index.js
app.onSync((body) => {
return {
requestId: body.requestId,
payload: {
agentUserId: USER_ID,
devices: [{
id: 'washer',
type: 'action.devices.types.WASHER',
traits: [
'action.devices.traits.OnOff',
'action.devices.traits.StartStop',
'action.devices.traits.RunCycle',
],
name: {
defaultNames: ['My Washer'],
name: 'Washer',
nicknames: ['Washer'],
},
deviceInfo: {
manufacturer: 'Acme Co',
model: 'acme-washer',
hwVersion: '1.0',
swVersion: '1.0.1',
},
willReportState: true,
attributes: {
pausable: true,
},
}],
},
};
});
Развертывание в Firebase
Разверните обновленное облачное выполнение с помощью интерфейса командной строки Firebase:
firebase deploy --only functions
Ссылка на Google Ассистент
Чтобы протестировать интеграцию между облаками, вам необходимо связать свой проект с учетной записью Google. Это позволяет проводить тестирование через поверхности Google Assistant и приложение Google Home, которые вошли в одну и ту же учетную запись.
- На телефоне откройте настройки Google Assistant. Обратите внимание, что вы должны войти в систему под той же учетной записью, что и в консоли.
- Перейдите в «Google Ассистент» > «Настройки» > «Управление домом» (в разделе «Ассистент»).
- Нажмите значок поиска в правом верхнем углу.
- Найдите свое тестовое приложение, используя префикс [test] , чтобы найти конкретное тестовое приложение.
- Выберите этот элемент. Затем Google Assistant пройдет аутентификацию в вашей службе и отправит запрос
SYNC
, попросив вашу службу предоставить пользователю список устройств.
Откройте приложение Google Home и убедитесь, что вы видите стиральную машину.
5. Обработка команд и запросов
Теперь, когда ваш облачный сервис правильно сообщает Google о стиральном устройстве, вам необходимо добавить возможность запрашивать состояние устройства и отправлять команды.
Обработка намерения QUERY
Намерение QUERY
включает в себя набор устройств. Для каждого устройства вы должны ответить его текущим состоянием.
В functions/index.js
отредактируйте обработчик QUERY
, чтобы обработать список целевых устройств, содержащийся в запросе намерения.
index.js
app.onQuery(async (body) => {
const {requestId} = body;
const payload = {
devices: {},
};
const queryPromises = [];
const intent = body.inputs[0];
for (const device of intent.payload.devices) {
const deviceId = device.id;
queryPromises.push(queryDevice(deviceId)
.then((data) => {
// Add response to device payload
payload.devices[deviceId] = data;
}
));
}
// Wait for all promises to resolve
await Promise.all(queryPromises);
return {
requestId: requestId,
payload: payload,
};
});
Для каждого устройства, содержащегося в запросе, верните текущее состояние, хранящееся в базе данных реального времени. Обновите функции queryFirebase
и queryDevice
, чтобы они возвращали данные о состоянии стиральной машины.
index.js
const queryFirebase = async (deviceId) => {
const snapshot = await firebaseRef.child(deviceId).once('value');
const snapshotVal = snapshot.val();
return {
on: snapshotVal.OnOff.on,
isPaused: snapshotVal.StartStop.isPaused,
isRunning: snapshotVal.StartStop.isRunning,
};
};
const queryDevice = async (deviceId) => {
const data = await queryFirebase(deviceId);
return {
on: data.on,
isPaused: data.isPaused,
isRunning: data.isRunning,
currentRunCycle: [{
currentCycle: 'rinse',
nextCycle: 'spin',
lang: 'en',
}],
currentTotalRemainingTime: 1212,
currentCycleRemainingTime: 301,
};
};
Обработка намерения EXECUTE
Намерение EXECUTE
обрабатывает команды для обновления состояния устройства. Ответ возвращает статус каждой команды — например, SUCCESS
, ERROR
или PENDING
— и новое состояние устройства.
В functions/index.js
отредактируйте обработчик EXECUTE
для обработки списка свойств, требующих обновления, и набора целевых устройств для каждой команды:
index.js
app.onExecute(async (body) => {
const {requestId} = body;
// Execution results are grouped by status
const result = {
ids: [],
status: 'SUCCESS',
states: {
online: true,
},
};
const executePromises = [];
const intent = body.inputs[0];
for (const command of intent.payload.commands) {
for (const device of command.devices) {
for (const execution of command.execution) {
executePromises.push(
updateDevice(execution, device.id)
.then((data) => {
result.ids.push(device.id);
Object.assign(result.states, data);
})
.catch(() => functions.logger.error('EXECUTE', device.id)));
}
}
}
await Promise.all(executePromises);
return {
requestId: requestId,
payload: {
commands: [result],
},
};
});
Для каждой команды и целевого устройства обновите значения в базе данных реального времени, соответствующие запрошенному признаку. Измените функцию updateDevice
, чтобы обновить соответствующую ссылку Firebase и вернуть обновленное состояние устройства.
index.js
const updateDevice = async (execution, deviceId) => {
const {params, command} = execution;
let state; let ref;
switch (command) {
case 'action.devices.commands.OnOff':
state = {on: params.on};
ref = firebaseRef.child(deviceId).child('OnOff');
break;
case 'action.devices.commands.StartStop':
state = params.start
? {isRunning: true, isPaused: false}
: {isRunning: false, isPaused: false};
ref = firebaseRef.child(deviceId).child('StartStop');
break;
case 'action.devices.commands.PauseUnpause':
const data = await queryDevice(deviceId);
state = (data.isPaused === false && data.isRunning === false)
? {isRunning: false, isPaused: false}
: {isRunning: !params.pause, isPaused: params.pause};
ref = firebaseRef.child(deviceId).child('StartStop');
break;
}
return ref.update(state)
.then(() => state);
};
6. Проверьте свою интеграцию
После реализации всех трех намерений вы можете проверить, контролирует ли ваша интеграция стиральную машину.
Развертывание в Firebase
Разверните обновленное облачное выполнение с помощью интерфейса командной строки Firebase:
firebase deploy --only functions
Проверьте стиральную машину
Теперь вы можете увидеть изменение значения, когда попробуете любую из следующих голосовых команд через телефон:
«Эй, Google, включи мою стиральную машину».
«Окей, Google, приостанови мою стиральную машину».
«Эй, Google, останови мою стиральную машину».
Вы также можете увидеть текущее состояние вашей стиральной машины, задавая вопросы.
«Окей, Google, моя стиральная машина включена?»
«Окей, Google, моя стиральная машина работает?»
«Окей, Google, на каком цикле работает моя стиральная машина?»
Вы можете просмотреть эти запросы и команды в журналах, которые отображаются под вашей функцией в разделе «Функции» консоли Firebase . Узнайте больше о журналах Firebase в разделе «Запись и просмотр журналов» .
Вы также можете найти эти запросы и команды в Google Cloud Console, перейдя в раздел «Ведение журналов» > «Обозреватель журналов» . Узнайте больше о ведении журналов Google Cloud в статье Доступ к журналам событий с помощью Cloud Logging .
7. Сообщайте об обновлениях в Google.
Вы полностью интегрировали свой облачный сервис с функциями умного дома, что позволяет пользователям контролировать и запрашивать текущее состояние своих устройств. Однако в реализации по-прежнему отсутствует возможность для вашей службы заранее отправлять информацию о событиях, например изменениях в присутствии или состоянии устройства, в Помощник.
С помощью Request Sync вы можете инициировать новый запрос на синхронизацию, когда пользователи добавляют или удаляют устройства или когда изменяются возможности их устройств. С помощью Report State ваша облачная служба может заранее отправлять состояние устройства в Home Graph, когда пользователи физически изменяют состояние устройства (например, включают выключатель света) или меняют состояние с помощью другой службы.
В этом разделе вы добавите код для вызова этих методов из внешнего веб-приложения.
Включите API HomeGraph
API HomeGraph позволяет хранить и запрашивать устройства и их состояния в Home Graph пользователя. Чтобы использовать этот API, необходимо сначала открыть консоль Google Cloud и включить HomeGraph API .
В консоли Google Cloud обязательно выберите проект, соответствующий вашей интеграции <project-id>.
Затем на экране библиотеки API для HomeGraph API нажмите « Включить» .
Включить состояние отчета
Запись в базу данных реального времени запускает функцию reportstate
в стартовом проекте. Обновите функцию reportstate
в functions/index.js
чтобы захватывать данные, записанные в базу данных, и публиковать их в Home Graph через Report State.
index.js
exports.reportstate = functions.database.ref('{deviceId}').onWrite(
async (change, context) => {
functions.logger.info('Firebase write event triggered Report State');
const snapshot = change.after.val();
const requestBody = {
requestId: 'ff36a3cc', /* Any unique ID */
agentUserId: USER_ID,
payload: {
devices: {
states: {
/* Report the current state of our washer */
[context.params.deviceId]: {
on: snapshot.OnOff.on,
isPaused: snapshot.StartStop.isPaused,
isRunning: snapshot.StartStop.isRunning,
},
},
},
},
};
const res = await homegraph.devices.reportStateAndNotification({
requestBody,
});
functions.logger.info('Report state response:', res.status, res.data);
});
Включить синхронизацию запросов
Обновление значка в веб-интерфейсе внешнего интерфейса запускает функцию requestsync
в стартовом проекте. Реализуйте функцию requestsync
в functions/index.js
для вызова API HomeGraph.
index.js
exports.requestsync = functions.https.onRequest(async (request, response) => {
response.set('Access-Control-Allow-Origin', '*');
functions.logger.info(`Request SYNC for user ${USER_ID}`);
try {
const res = await homegraph.devices.requestSync({
requestBody: {
agentUserId: USER_ID,
},
});
functions.logger.info('Request sync response:', res.status, res.data);
response.json(res.data);
} catch (err) {
functions.logger.error(err);
response.status(500).send(`Error requesting sync: ${err}`);
}
});
Развертывание в Firebase
Разверните обновленный код с помощью Firebase CLI:
firebase deploy --only functions
Проверьте свою реализацию
Нажмите Обновить в веб-интерфейсе и убедитесь, что вы видите запрос синхронизации в журнале консоли Firebase.
Затем настройте атрибуты стирального устройства в интерфейсном веб-интерфейсе и нажмите «Обновить» . Убедитесь, что вы видите изменение состояния, о котором сообщается в Google, в журналах консоли Firebase.
8. Поздравления
Поздравляем! Вы успешно интегрировали Ассистент с облачной службой устройства с помощью интеграции «облако-облако».
Узнать больше
Вот несколько идей, которые вы можете реализовать, чтобы пойти глубже:
- Добавляйте режимы и переключатели на свое устройство.
- Добавьте на свое устройство больше поддерживаемых функций .
- Ознакомьтесь с локальным исполнением умного дома.
- Чтобы узнать больше, ознакомьтесь с нашим примером на GitHub .
Вы также можете узнать больше о тестировании и отправке интеграции на рассмотрение, включая процесс сертификации для публикации вашей интеграции для пользователей.