1. Zanim zaczniesz
Jako deweloper Internetu Rzeczy (IoT) możesz tworzyć integracje typu chmura-chmura, które umożliwiają użytkownikom sterowanie urządzeniami za pomocą elementów sterujących dotykowych w aplikacji Google Home i poleceń głosowych kierowanych do Asystenta.
Integracje typu cloud-to-cloud korzystają z Home Graph, aby dostarczać dane kontekstowe o domu i jego urządzeniach, tworząc logiczną mapę domu. Ten kontekst pozwala Asystentowi lepiej rozumieć prośby użytkownika w odniesieniu do jego lokalizacji w domu. Na przykład Home Graph może przechowywać koncepcję salonu, w którym znajdują się różne typy urządzeń od różnych producentów, takie jak termostat, lampa, wentylator i odkurzacz.
Wymagania wstępne
- Tworzenie integracji typu chmura-chmura – przewodnik dla deweloperów
Co utworzysz
W tym module opublikujesz usługę w chmurze, która zarządza wirtualną inteligentną pralką, a następnie utworzysz integrację typu chmura-chmura i połączysz ją z Asystentem.
Czego się nauczysz
- Jak wdrożyć usługę w chmurze dla inteligentnego domu
- Jak połączyć usługę z Asystentem
- Jak publikować zmiany stanu urządzenia w Google
Czego potrzebujesz
- przeglądarka, np. Google Chrome;
- Urządzenie z iOS lub Androidem z zainstalowaną aplikacją Google Home
- Node.js w wersji 10.16 lub nowszej
- konto rozliczeniowe Google Cloud;
2. Pierwsze kroki
Włączanie zarządzania aktywnością
Aby korzystać z Asystenta Google, musisz udostępniać Google określone dane o aktywności. Asystent Google potrzebuje tych danych do prawidłowego działania, ale wymóg udostępniania danych nie jest specyficzny dla pakietu SDK. Aby udostępniać te dane, utwórz konto Google, jeśli jeszcze go nie masz. Możesz użyć dowolnego konta Google, nie musi to być konto dewelopera.
Otwórz stronę Zarządzanie aktywnością na koncie Google, którego chcesz używać z Asystentem.
Upewnij się, że te przełączniki są włączone:
- Aktywność w internecie i aplikacjach – dodatkowo zaznacz pole Uwzględnij historię Chrome i aktywność na stronach, urządzeniach i w aplikacjach, które używają usług Google.
- Informacje o urządzeniu
- Aktywność związana z głosem i dźwiękiem
Tworzenie projektu integracji typu chmura-chmura
- Otwórz Developer Console.
- Kliknij Utwórz projekt, wpisz nazwę projektu i kliknij Utwórz projekt.
Wybierz integrację typu chmura-chmura
Na stronie Strona główna projektu w konsoli dewelopera w sekcji Cloud-to-cloud kliknij Add cloud-to-cloud integration (Dodaj integrację cloud-to-cloud).
Instalowanie wiersza poleceń Firebase
Wiersz poleceń Firebase umożliwia lokalne udostępnianie aplikacji internetowych i wdrażanie ich w Hostingu Firebase.
Aby zainstalować interfejs wiersza poleceń, uruchom to polecenie npm w terminalu:
npm install -g firebase-tools
Aby sprawdzić, czy interfejs CLI został prawidłowo zainstalowany, uruchom to polecenie:
firebase --version
Autoryzuj wiersz poleceń Firebase za pomocą konta Google, uruchamiając to polecenie:
firebase login
3. Uruchamianie aplikacji wyjściowej
Po skonfigurowaniu środowiska programistycznego możesz wdrożyć projekt początkowy, aby sprawdzić, czy wszystko jest prawidłowo skonfigurowane.
Pobieranie kodu źródłowego
Kliknij ten link, aby pobrać na komputer, którego używasz do programowania, przykładowy kod do tego laboratorium:
Możesz też sklonować repozytorium GitHub z poziomu wiersza poleceń:
git clone https://github.com/google-home/smarthome-washer.git
Informacje o projekcie
Projekt początkowy zawiera te podkatalogi:
public:
Interfejs użytkownika, który umożliwia łatwe sterowanie stanem inteligentnej pralki i jego monitorowanie.functions:
W pełni wdrożona usługa w chmurze, która zarządza inteligentną pralką za pomocą Cloud Functions dla Firebase i Bazy danych czasu rzeczywistego Firebase.
Dodawanie Firebase do projektu w konsoli programisty Google Home
Metoda 1. W konsoli Firebase
- Otwórz Firebase.
- Kliknij Utwórz projekt Firebase.
- Na ekranie Utwórz projekt kliknij Dodaj Firebase do projektu Google Cloud.
- Na ekranie Rozpocznij wybierz projekt Google Cloud, który został utworzony w konsoli Google Home Developer, a następnie kliknij Dalej.
Metoda 2. Za pomocą wiersza poleceń Firebase
firebase projects:addfirebase
Aby dodać Firebase, wybierz utworzony projekt w Konsoli dewelopera Google Home.
Gdy dodasz Firebase do projektu w Google Home Developer Console, pojawi się on w konsoli Firebase. Identyfikator projektu Firebase będzie zgodny z identyfikatorem projektu w konsoli dewelopera Google Home.
Łączenie Analytics z Firebase
Otwórz katalog washer-start
, a potem skonfiguruj wiersz poleceń Firebase za pomocą projektu integracji:
cd washer-start firebase use <project-id>
Konfigurowanie projektu Firebase
Zainicjuj projekt Firebase.
firebase init
Wybierz funkcje interfejsu CLI, Realtime Database i Functions.
? Which Firebase features do you want to set up for this directory? Press Space to select features, then Enter to confirm your choices. (Press <space> to select, <a> to toggle all, <i> to invert selection, and <enter> to proceed) >( ) Data Connect: Set up a Firebase Data Connect service ( ) Firestore: Configure security rules and indexes files for Firestore ( ) Genkit: Setup a new Genkit project with Firebase (*) Functions: Configure a Cloud Functions directory and its files ( ) App Hosting: Configure an apphosting.yaml file for App Hosting ( ) Hosting: Configure files for Firebase Hosting and (optionally) 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 (*) Realtime Database: Configure a security rules file for Realtime Database and (optionally) provision default instance ( ) Data Connect: Set up a Firebase Data Connect service ( ) Firestore: Configure security rules and indexes files for Firestore
Spowoduje to zainicjowanie niezbędnych interfejsów API i funkcji w projekcie.
Gdy pojawi się odpowiedni komunikat, zainicjuj bazę danych czasu rzeczywistego. Możesz użyć domyślnej lokalizacji instancji bazy danych.
? 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
Ponieważ używasz kodu projektu początkowego, wybierz domyślny plik reguł zabezpieczeń i upewnij się, że nie zastąpisz istniejącego pliku reguł bazy danych.
? 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
Jeśli ponownie inicjujesz projekt, gdy pojawi się pytanie, czy chcesz zainicjować lub zastąpić bazę kodu, kliknij Zastąp.
? Would you like to initialize a new codebase, or overwrite an existing one? Overwrite
Podczas konfigurowania funkcji używaj domyślnych plików i upewnij się, że nie zastępujesz istniejących plików index.js i package.json w przykładowym projekcie.
? 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
Jeśli ponownie inicjujesz projekt, na pytanie, czy chcesz zainicjować lub zastąpić plik functions/.gitignore, wybierz Nie.
? File functions/.gitignore already exists. Overwrite? No
? Do you want to install dependencies with npm now? Yes
Jeśli ESLint został przypadkowo włączony, można go wyłączyć na 2 sposoby:
- W GUI przejdź do folderu
../functions
w projekcie, wybierz ukryty plik.eslintrc.js
i usuń go. Nie myl go z podobnie nazwanym.eslintrc.json
. - W wierszu poleceń:
cd functions rm .eslintrc.js
W pliku washer-start/firebase.json
uzupełnij kod o:
{
"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"
]
}
]
}
Wdrażanie w Firebase
Po zainstalowaniu zależności i skonfigurowaniu projektu możesz po raz pierwszy uruchomić aplikację.
firebase deploy
Oto dane wyjściowe, które powinny się wyświetlić w konsoli:
... ✔ Deploy complete! Project Console: https://console.firebase.google.com/project/<project-id>/overview Hosting URL: https://<project-id>.web.app
To polecenie wdraża aplikację internetową wraz z kilkoma Cloud Functions dla Firebase.
Otwórz adres URL hostingu w przeglądarce (https://<project-id>.web.app
), aby wyświetlić aplikację internetową. Zobaczysz ten interfejs:
Ten interfejs internetowy to platforma innej firmy, która umożliwia wyświetlanie i modyfikowanie stanów urządzeń. Aby rozpocząć wypełnianie bazy danych informacjami o urządzeniach, kliknij AKTUALIZUJ. Na stronie nie zobaczysz żadnych zmian, ale bieżący stan pralki zostanie zapisany w bazie danych.
Teraz musisz połączyć wdrożoną usługę w chmurze z Asystentem Google za pomocą Konsoli dewelopera Google Home.
Konfigurowanie projektu w Konsoli programisty
Na karcie Opracowywanie dodaj wyświetlaną nazwę interakcji. Ta nazwa będzie widoczna w aplikacji Google Home.
W sekcji Branding aplikacji prześlij plik png
z ikoną aplikacji o rozmiarach 144 x 144 pikseli i nazwie
.
Aby włączyć łączenie kont, użyj tych ustawień łączenia kont:
Identyfikator klienta |
|
Tajny klucz klienta |
|
Adres URL autoryzacji |
|
URL tokena |
|
W sekcji Adres URL realizacji w chmurze wpisz adres URL funkcji w Cloud Functions, która zapewnia realizację intencji związanych z inteligentnym domem.
https://us-central1-<project-id>.cloudfunctions.net/smarthome
Aby zapisać konfigurację projektu, kliknij Zapisz, a potem Dalej: testowanie, aby włączyć testowanie w projekcie.
Teraz możesz zacząć wdrażać elementy webhook, które są niezbędne do połączenia stanu urządzenia z Asystentem.
4. Tworzenie podkładki
Po skonfigurowaniu integracji możesz dodawać urządzenia i wysyłać dane. Usługa w chmurze musi obsługiwać te intencje:
SYNC
zamiar pojawia się, gdy Asystent chce się dowiedzieć, jakie urządzenia są połączone z użytkownikiem. Jest on wysyłany do Twojej usługi, gdy użytkownik połączy konto. Powinieneś odpowiedzieć ładunkiem JSON zawierającym wszystkie urządzenia użytkownika i ich możliwości.QUERY
Intencja występuje, gdy Asystent chce poznać bieżący stan urządzenia. Powinna zwrócić ładunek JSON ze stanem każdego żądanego urządzenia.EXECUTE
to intencja, która pojawia się, gdy Asystent chce sterować urządzeniem w imieniu użytkownika. Powinieneś odpowiedzieć ładunkiem JSON ze stanem wykonania każdego żądanego urządzenia.DISCONNECT
występuje, gdy użytkownik odłączy swoje konto od Asystenta. Przestań wysyłać do Asystenta Google wydarzenia z urządzeń tego użytkownika.
W kolejnych sekcjach zaktualizujesz funkcje, które zostały wcześniej wdrożone do obsługi tych intencji.
Aktualizowanie odpowiedzi SYNC
Otwórz plik functions/index.js
, który zawiera kod do odpowiadania na żądania Asystenta.
Musisz obsłużyć SYNC
intencję, zwracając metadane i możliwości urządzenia. Zaktualizuj kod JSON w onSync
, aby uwzględnić informacje o urządzeniu i zalecane cechy pralki.
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,
},
}],
},
};
});
Wdrażanie w Firebase
Wdróż zaktualizowaną realizację w chmurze za pomocą wiersza poleceń Firebase:
firebase deploy --only functions
Łączenie z Asystentem Google
Aby przetestować integrację typu cloud-to-cloud, musisz połączyć projekt z kontem Google. Umożliwia to testowanie na urządzeniach z Asystentem Google i w aplikacji Google Home, na których zalogowano się na to samo konto.
- Otwórz ustawienia Asystenta Google na telefonie. Pamiętaj, aby zalogować się na to samo konto co w konsoli.
- Wybierz Asystent Google > Ustawienia > Sterowanie domem (w sekcji Asystent).
- W prawym górnym rogu kliknij ikonę wyszukiwania.
- Wyszukaj aplikację testową, używając prefiksu [test].
- Wybierz ten element. Asystent Google uwierzytelni się w usłudze i wyśle żądanie
SYNC
, prosząc o podanie listy urządzeń użytkownika.
Otwórz aplikację Google Home i sprawdź, czy widzisz urządzenie do prania.
5. Obsługa poleceń i zapytań
Teraz, gdy usługa w chmurze prawidłowo zgłasza urządzenie do Google, musisz dodać możliwość wysyłania poleceń i żądania stanu urządzenia.
Obsługa intencji QUERY
QUERY
Intencja obejmuje zestaw urządzeń. W przypadku każdego urządzenia podaj jego aktualny stan.
W functions/index.js
zmień moduł obsługi QUERY
, aby przetwarzać listę urządzeń docelowych zawartą w żądaniu intencji.
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,
};
});
W przypadku każdego urządzenia zawartego w żądaniu zwraca bieżący stan przechowywany w bazie danych czasu rzeczywistego. Zaktualizuj funkcje queryFirebase
i queryDevice
, aby zwracały dane o stanie pralki.
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,
};
};
Obsługa intencji EXECUTE
EXECUTE
Intencja obsługuje polecenia aktualizowania stanu urządzenia. Odpowiedź zawiera stan każdego polecenia, np. SUCCESS
, ERROR
lub PENDING
, oraz nowy stan urządzenia.
W functions/index.js
zmień moduł obsługi EXECUTE
, aby przetwarzać listę cech, które wymagają aktualizacji, oraz zestaw urządzeń docelowych dla każdego polecenia:
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],
},
};
});
W przypadku każdego polecenia i urządzenia docelowego zaktualizuj w bazie danych czasu rzeczywistego wartości odpowiadające żądanej cesze. Zmodyfikuj funkcję updateDevice
, aby zaktualizować odpowiednie odwołanie do Firebase i zwrócić zaktualizowany stan urządzenia.
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. Testowanie integracji
Po zaimplementowaniu wszystkich 3 intencji możesz sprawdzić, czy integracja steruje pralką.
Wdrażanie w Firebase
Wdróż zaktualizowaną realizację w chmurze za pomocą wiersza poleceń Firebase:
firebase deploy --only functions
Testowanie pralki
Teraz możesz zobaczyć zmianę wartości, gdy wypróbujesz na telefonie dowolne z tych poleceń głosowych:
„OK Google, włącz pralkę”.
„OK Google, wstrzymaj pranie”.
„OK Google, zatrzymaj pralkę”
Możesz też sprawdzić aktualny stan pralki, zadając pytania.
„OK Google, czy pralka jest włączona?”
„OK Google, czy pralka działa?”
„OK Google, w jakim cyklu pracuje pralka?”
Te zapytania i polecenia możesz wyświetlić w dziennikach, które pojawiają się pod funkcją w sekcji Funkcje w konsoli Firebase. Więcej informacji o logach Firebase znajdziesz w artykule Pisanie i wyświetlanie logów.
Te zapytania i polecenia znajdziesz też w konsoli Google Cloud, klikając Logowanie > Eksplorator logów. Więcej informacji o logowaniu w Google Cloud znajdziesz w artykule Uzyskiwanie dostępu do dzienników zdarzeń za pomocą Cloud Logging.
7. Zgłaszanie aktualizacji do Google
Usługa w chmurze jest w pełni zintegrowana z intencjami inteligentnego domu, co umożliwia użytkownikom sterowanie urządzeniami i sprawdzanie ich bieżącego stanu. Jednak wdrożenie nadal nie umożliwia usłudze proaktywnego wysyłania do Asystenta informacji o zdarzeniach, takich jak zmiany w obecności lub stanie urządzenia.
Za pomocą funkcji Request Sync możesz wywołać nową prośbę o synchronizację, gdy użytkownicy dodają lub usuwają urządzenia albo gdy zmieniają się możliwości ich urządzeń. Dzięki funkcji Report State usługa w chmurze może proaktywnie wysyłać stan urządzenia do Home Graph, gdy użytkownicy fizycznie zmieniają stan urządzenia (np. włączają włącznik światła) lub zmieniają stan za pomocą innej usługi.
W tej sekcji dodasz kod, który będzie wywoływać te metody z frontendowej aplikacji internetowej.
Włączanie interfejsu HomeGraph API
HomeGraph API umożliwia przechowywanie urządzeń i ich stanów w Home Graph użytkownika oraz wysyłanie zapytań dotyczących tych informacji. Aby korzystać z tego interfejsu API, musisz najpierw otworzyć konsolę Google Cloud i włączyć HomeGraph API.
W konsoli Google Cloud wybierz projekt, który pasuje do Twojej integracji <project-id>.
. Następnie na ekranie Biblioteka interfejsów API dla HomeGraph API kliknij Włącz.
Włącz raportowanie stanu
Zapisy w bazie danych czasu rzeczywistego wywołują funkcję reportstate
w projekcie startowym. Zaktualizuj funkcję reportstate
w functions/index.js
, aby rejestrować dane zapisywane w bazie danych i przesyłać je do Home Graph za pomocą funkcji 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);
});
Włącz synchronizację żądań
Odświeżenie ikony w interfejsie internetowym wywołuje funkcję requestsync
w projekcie startowym. Zaimplementuj funkcję requestsync
w functions/index.js
, aby wywoływać interfejs HomeGraph API.
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}`);
}
});
Wdrażanie w Firebase
Wdróż zaktualizowany kod za pomocą wiersza poleceń Firebase:
firebase deploy --only functions
Testowanie implementacji
W interfejsie internetowym kliknij przycisk Odśwież i sprawdź, czy w dzienniku konsoli Firebase widzisz prośbę o synchronizację.
Następnie dostosuj atrybuty pralki w interfejsie internetowym i kliknij Zaktualizuj. Sprawdź, czy w logach konsoli Firebase widzisz zmianę stanu zgłoszoną do Google.
8. Gratulacje
Gratulacje! Udało Ci się zintegrować Asystenta z usługą w chmurze urządzenia za pomocą integracji typu chmura-chmura.
Więcej informacji
Oto kilka pomysłów, które pomogą Ci pogłębić wiedzę:
- Dodaj do urządzenia tryby i przełączniki.
- Dodaj do urządzenia więcej obsługiwanych cech.
- Dowiedz się więcej o lokalnym wykonywaniu w przypadku inteligentnego domu.
- Więcej informacji znajdziesz w naszym przykładzie w GitHubie.
Możesz też dowiedzieć się więcej o testowaniu i przesyłaniu integracji do sprawdzenia, w tym o procesie certyfikacji, który umożliwia opublikowanie integracji dla użytkowników.