1. Zanim zaczniesz
Integracje między chmurami używają typów urządzeń, aby poinformować Asystenta Google, jakiej gramatyki używać na danym urządzeniu. Cechy urządzenia określają możliwości danego typu urządzenia. Urządzenie dziedziczy stany wszystkich atrybutów urządzenia dodanych do integracji.
Aby dostosować funkcje urządzeń użytkowników, możesz połączyć dowolne obsługiwane cechy z wybranym typem urządzenia. Jeśli chcesz wdrożyć w swoich działaniach cechy niestandardowe, które nie są obecnie dostępne w schemacie urządzenia, cechy Tryby i Przełączniki umożliwiają sterowanie określonymi ustawieniami za pomocą zdefiniowanej przez Ciebie nazwy.
Oprócz podstawowych funkcji sterowania zapewnianych przez typy i cechy interfejs Smart Home API oferuje dodatkowe funkcje, które zwiększają wygodę użytkowania. Odpowiedzi na błędy zawierają szczegółowe informacje o użytkowniku, gdy intencja nie powiedzie się. Weryfikacja przez drugiego użytkownika rozszerza te odpowiedzi i zapewnia dodatkową ochronę wybranej przez Ciebie cechy urządzenia. Wysyłając określone odpowiedzi na błędy w blokach wyzwań wydawanych przez Asystenta, integracja między chmurami może wymagać dodatkowego autoryzowania, aby wykonać polecenie.
Wymagania wstępne
- Tworzenie integracji między chmurami – przewodnik dla deweloperów
- Ćwiczenie z programowania Inteligentna pralka
- Przewodnik dla deweloperów dotyczący typów i cech urządzeń
Co utworzysz
W tym ćwiczeniu z programowania wprowadzisz gotową integrację inteligentnego domu z Firebase, a potem dowiesz się, jak dodać do inteligentnej pralki cechy niestandardowe, takie jak rozmiar załadunku i tryb turbo. Wdrożysz też raportowanie błędów i wyjątków oraz nauczysz się wymagać potwierdzenia słownego włączenia pralki za pomocą weryfikacji dodatkowego użytkownika.
Czego się nauczysz
- Jak dodać cechy trybów i przełączników do integracji
- Jak zgłaszać błędy i wyjątki
- Jak przeprowadzić dodatkową weryfikację użytkownika
Czego potrzebujesz
- przeglądarka internetowa, np. Google Chrome;
- urządzenie z iOS lub Androidem z zainstalowaną aplikacją Google Home;
- Node.js w wersji 10.16 lub nowszej
- konto Google,
- konto rozliczeniowe Google Cloud;
2. Pierwsze kroki
Włączanie Zarządzania aktywnością
Aby korzystać z Asystenta Google, musisz udostępnić Google określone dane o aktywności. Asystent Google potrzebuje tych danych do prawidłowego działania, ale udostępnianie danych nie jest wymagane w przypadku 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ć Twoje 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 – pamiętaj też, aby zaznaczyć pole wyboru 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 między chmurami
- Otwórz konsolę dewelopera.
- Kliknij Utwórz projekt, wpisz nazwę projektu i kliknij Utwórz projekt.
Wybierz integrację chmur
W sekcji Cloud-to-cloud (Między chmurami) na stronie Project Home (Strona projektu) w Konsoli programisty kliknij Add cloud-to-cloud integration (Dodaj integrację między chmurami).
Zainstaluj wiersz poleceń Firebase
Interfejs wiersza poleceń Firebase (CLI) umożliwia obsługę aplikacji internetowych lokalnie i wdrażanie ich do hostingu Firebase.
Aby zainstalować interfejs wiersza poleceń, uruchom w terminalu to polecenie npm:
npm install -g firebase-tools
Aby sprawdzić, czy interfejs wiersza poleceń został prawidłowo zainstalowany, uruchom:
firebase --version
Autoryzuj wiersz poleceń Firebase za pomocą swojego konta Google, wykonując:
firebase login
Tworzenie projektu Firebase
- Otwórz Firebase.
- Kliknij Utwórz projekt i wpisz nazwę projektu.
- Zaznacz pole wyboru akceptacji i kliknij Dalej. Jeśli nie ma pola wyboru dotyczącego umowy, możesz pominąć ten krok.
- Po utworzeniu projektu Firebase odszukaj jego identyfikator. Kliknij Przegląd projektu, a potem ikonę ustawień > Ustawienia projektu.
- Twój projekt jest widoczny na karcie Ogólne.
Włącz interfejs HomeGraph API
Interfejs HomeGraph API umożliwia przechowywanie urządzeń i ich stanów oraz wysyłanie zapytań o te dane w ramach Home Graph użytkownika. Aby korzystać z tego interfejsu API, musisz najpierw otworzyć konsolę Google Cloud i włączyć interfejs HomeGraph API.
W konsoli Google Cloud wybierz projekt, który odpowiada Twoim działaniom. <firebase-project-id>.
Następnie na ekranie Biblioteka interfejsów API dla interfejsu HomeGraph API kliknij Włącz.
3. Uruchamianie aplikacji startowej
Gdy już skonfigurujesz środowisko programistyczne, możesz wdrożyć projekt startowy, aby sprawdzić, czy wszystko jest prawidłowo skonfigurowane.
Pobieranie kodu źródłowego
Aby pobrać na maszynę programistyczną przykładowy projekt tego ćwiczenia, kliknij ten link:
...lub możesz sklonować repozytorium GitHub z poziomu wiersza poleceń:
git clone https://github.com/google-home/smarthome-traits.git
Rozpakuj pobrany plik ZIP.
Informacje o projekcie
Projekt startowy zawiera te katalogi podrzędne:
public:
Interfejs użytkownika umożliwiający łatwe sterowanie pralką i monitorowanie jej stanu.functions:
W pełni zaimplementowana usługa w chmurze, która zarządza inteligentną pralką za pomocą Cloud Functions dla Firebase i Bazy danych czasu rzeczywistego Firebase.
Udostępnione rozwiązanie w chmurze obejmuje te funkcje w usłudze index.js
:
fakeauth
: punkt końcowy autoryzacji do łączenia kontfaketoken
: punkt końcowy tokena do łączenia kontsmarthome
: punkt końcowy realizacji intencji w ramach inteligentnego domureportstate
: wywołuje interfejs Home Graph API po zmianie stanu urządzenia.requestsync
: umożliwia aktualizacje na urządzeniu użytkownika bez konieczności ponownego łączenia konta.
Połącz się z Firebase
Przejdź do katalogu washer-start
, a potem skonfiguruj wiersz poleceń Firebase w ramach projektu integracji:
cd washer-start firebase use <firebase-project-id>
Skonfiguruj projekt Firebase
Inicjalizacja projektu Firebase.
firebase init
Wybierz funkcje wiersza poleceń, Baza danych czasu rzeczywistego, Funkcje i funkcję Hosting, która obejmuje Hosting 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
Spowoduje to zainicjowanie niezbędnych interfejsów API i funkcji w projekcie.
Po wyświetleniu odpowiedniej prośby zainicjuj bazę danych Firebase Realtime Database. Możesz użyć domyślnej lokalizacji dla 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 podstawowego, 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, wybierz Zastąp.
? Would you like to initialize a new codebase, or overwrite an existing one? Overwrite
Podczas konfigurowania funkcji użyj plików domyślnych i upewnij się, że nie zastąpisz istniejących plików index.js i package.json w próbnym 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, gdy pojawi się pytanie, czy chcesz zainicjować lub zastąpić pliki functions/.gitignore, wybierz Nie.
? File functions/.gitignore already exists. Overwrite? No
? Do you want to install dependencies with npm now? Yes
Na koniec skonfiguruj ustawienia hostingu, aby używać katalogu public
w kodzie projektu, i użyj istniejącego pliku index.html. Gdy pojawi się pytanie o używanie ESLint, wybierz Nie.
? 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
Jeśli ESLint zostało przypadkowo włączone, możesz je wyłączyć na 2 sposoby:
- Za pomocą interfejsu graficznego przejdź do folderu
../functions
w ramach projektu, wybierz ukryty plik.eslintrc.js
i usuń go. Nie myl go z elementem o podobnej nazwie.eslintrc.json
. - W wierszu poleceń:
cd functions rm .eslintrc.js
Wdrażanie w Firebase
Po zainstalowaniu zależności i skonfigurowaniu projektu możesz uruchomić aplikację po raz pierwszy.
firebase deploy
Dane wyjściowe konsoli powinny wyglądać tak:
... ✔ Deploy complete! Project Console: https://console.firebase.google.com/project/<firebase-project-id>/overview Hosting URL: https://<firebase-project-id>.web.app
To polecenie wdraża aplikację internetową wraz z kilkoma funkcjami Cloud Functions dla Firebase.
Aby wyświetlić aplikację internetową, otwórz w przeglądarce (https://<firebase-project-id>.web.app
) adres URL hostingu. Zobaczysz ten interfejs:
Ten interfejs internetowy reprezentuje platformę innej firmy, która umożliwia wyświetlanie i modyfikowanie stanów urządzenia. Aby rozpocząć wypełnianie bazy danych informacjami o urządzeniach, kliknij Zaktualizuj. Nie zobaczysz żadnych zmian na stronie, ale bieżący stan pralki zostanie zapisany w bazie danych.
Teraz musisz połączyć wdrożony przez siebie serwis w chmurze z Asystentem Google za pomocą Konsoli dla deweloperów.
Konfigurowanie projektu w Konsoli deweloperów
Na karcie Tworzenie dodaj Wyświetlaną nazwę interakcji. Ta nazwa będzie widoczna w aplikacji Google Home.
W sekcji Marka aplikacji prześlij plik png
ikony aplikacji o rozmiarze 144 × 144 pikseli i nazwie
.
Aby włączyć łączenie kont, użyj tych ustawień:
Identyfikator klienta |
|
Tajny klucz klienta |
|
Adres URL autoryzacji |
|
Adres URL tokena |
|
W sekcji URL realizacji w chmurze wpisz adres URL funkcji w chmurze, która zapewnia realizację intencji związanych z inteligentnym domem.
https://us-central1-
Aby zapisać konfigurację projektu, kliknij Zapisz, a potem kliknij Dalej: testowanie, aby włączyć testowanie projektu.
Teraz możesz zacząć wdrażać webhooki niezbędne do połączenia stanu urządzenia z Asystentem.
Łączenie z Asystentem Google
Aby przetestować integrację między chmurami, musisz połączyć projekt z kontem Google. Umożliwia to testowanie w interfejsach Asystenta Google i aplikacji Google Home, w których użytkownik jest zalogowany na to samo konto.
- Na telefonie otwórz ustawienia Asystenta Google. Pamiętaj, że musisz zalogować się na to samo konto, którego używasz w konsoli.
- Kliknij Asystent Google > Ustawienia > Sterowanie domem (w sekcji Asystent).
- W prawym górnym rogu kliknij ikonę wyszukiwania.
- Aby znaleźć konkretną aplikację testową, wyszukaj ją, używając prefiksu [test].
- Wybierz ten element. Asystent Google uwierzytelnia się w Twojej usłudze i wysyła żądanie
SYNC
, aby Twoja usługa podała listę urządzeń użytkownika.
Otwórz aplikację Google Home i sprawdź, czy widzisz swoją pralkę.
Sprawdź, czy możesz sterować pralką za pomocą poleceń głosowych w aplikacji Google Home. Powinieneś też zobaczyć zmianę stanu urządzenia w interfejsie internetowym usługi w chmurze.
Po wdrożenie podstawowej pralki możesz dostosować tryby dostępne na urządzeniu.
4. Dodawanie trybów
Właściwość action.devices.traits.Modes
umożliwia urządzeniu ustawienie dowolnej liczby ustawień dla danego trybu, z których można wybrać tylko jedno. Dodasz do pralki tryb, który określi rozmiar ładunku: mały, średni lub duży.
Aktualizacja odpowiedzi SYNC
Musisz dodać informacje o nowej cesze do odpowiedzi SYNC
w sekcji functions/index.js
. Te dane są dostępne w tablicy traits
i obiekcie attributes
, jak pokazano w tym fragmencie kodu.
index.js
app.onSync(body => {
return {
requestId: 'ff36a3cc-ec34-11e6-b1a0-64510650abcf',
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',
// Add Modes trait
'action.devices.traits.Modes',
],
name: { ... },
deviceInfo: { ... },
attributes: {
pausable: true,
//Add availableModes
availableModes: [{
name: 'load',
name_values: [{
name_synonym: ['load'],
lang: 'en',
}],
settings: [{
setting_name: 'small',
setting_values: [{
setting_synonym: ['small'],
lang: 'en',
}]
}, {
setting_name: 'medium',
setting_values: [{
setting_synonym: ['medium'],
lang: 'en',
}]
}, {
setting_name: 'large',
setting_values: [{
setting_synonym: ['large'],
lang: 'en',
}]
}],
ordered: true,
}],
},
}],
},
};
});
Dodawanie nowych poleceń o zamiarze WYKONANIE
W intencji EXECUTE
dodaj polecenie action.devices.commands.SetModes
, jak pokazano w tym fragmencie kodu.
index.js
const updateDevice = async (execution,deviceId) => {
const {params,command} = execution;
let state, 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 = {isRunning: params.start};
ref = firebaseRef.child(deviceId).child('StartStop');
break;
case 'action.devices.commands.PauseUnpause':
state = {isPaused: params.pause};
ref = firebaseRef.child(deviceId).child('StartStop');
Break;
// Add SetModes command
case 'action.devices.commands.SetModes':
state = {load: params.updateModeSettings.load};
ref = firebaseRef.child(deviceId).child('Modes');
break;
}
Aktualizowanie odpowiedzi funkcji QUERY
Następnie zaktualizuj odpowiedź QUERY
, aby zgłosić aktualny stan pralki.
Dodaj zaktualizowane zmiany do funkcji queryFirebase
i queryDevice
, aby uzyskać stan zapisany w Baza danych w czasie rzeczywistym.
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,
// Add Modes snapshot
load: snapshotVal.Modes.load,
};
}
const queryDevice = async (deviceId) => {
const data = await queryFirebase(deviceId);
return {
on: data.on,
isPaused: data.isPaused,
isRunning: data.isRunning,
currentRunCycle: [{ ... }],
currentTotalRemainingTime: 1212,
currentCycleRemainingTime: 301,
// Add currentModeSettings
currentModeSettings: {
load: data.load,
},
};
};
Aktualizowanie stanu raportu
Na koniec zaktualizuj funkcję reportstate
, aby przekazywać do Graph Home informacje o bieżącym ustawieniu prania.
index.js
const requestBody = {
requestId: 'ff36a3cc', /* Any unique ID */
agentUserId: USER_ID,
payload: {
devices: {
states: {
/* Report the current state of your washer */
[context.params.deviceId]: {
on: snapshot.OnOff.on,
isPaused: snapshot.StartStop.isPaused,
isRunning: snapshot.StartStop.isRunning,
// Add currentModeSettings
currentModeSettings: {
load: snapshot.Modes.load,
},
},
},
},
},
};
Wdrażanie w Firebase
Aby wdrożyć zaktualizowaną integrację, uruchom to polecenie:
firebase deploy --only functions
Po zakończeniu wdrażania przejdź do interfejsu internetowego i na pasku narzędzi kliknij przycisk Odśwież . Spowoduje to wysłanie żądania synchronizacji, aby Asystent otrzymał zaktualizowane dane odpowiedzi
SYNC
.
Teraz możesz wydać polecenie, aby ustawić tryb pralki, na przykład:
„OK Google, ustaw pranie na dużą ilość”.
Dodatkowo możesz zadawać pytania dotyczące pralki, takie jak:
„OK Google, ile jest prania?”
5. Dodawanie przełączników
Właściwość action.devices.traits.Toggles
reprezentuje nazwane aspekty urządzenia, które mają stan prawda lub fałsz, np. czy pralka jest w trybie turbo.
Aktualizacja odpowiedzi SYNC
W odpowiedzi na SYNC
musisz dodać informacje o nowej właściwości urządzenia. Pojawi się on w tablicy traits
i obiekcie attributes
, jak pokazano w tym fragmencie kodu.
index.js
app.onSync(body => {
return {
requestId: 'ff36a3cc-ec34-11e6-b1a0-64510650abcf',
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',
'action.devices.traits.Modes',
// Add Toggles trait
'action.devices.traits.Toggles',
],
name: { ... },
deviceInfo: { ... },
attributes: {
pausable: true,
availableModes: [{
name: 'load',
name_values: [{
name_synonym: ['load'],
lang: 'en'
}],
settings: [{ ... }],
ordered: true,
}],
//Add availableToggles
availableToggles: [{
name: 'Turbo',
name_values: [{
name_synonym: ['turbo'],
lang: 'en',
}],
}],
},
}],
},
};
});
Dodawanie nowych poleceń o zamiarze EKSEKWUJ
W intencji EXECUTE
dodaj polecenie action.devices.commands.SetToggles
, jak pokazano w tym fragmencie kodu.
index.js
const updateDevice = async (execution,deviceId) => {
const {params,command} = execution;
let state, 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 = {isRunning: params.start};
ref = firebaseRef.child(deviceId).child('StartStop');
break;
case 'action.devices.commands.PauseUnpause':
state = {isPaused: params.pause};
ref = firebaseRef.child(deviceId).child('StartStop');
break;
case 'action.devices.commands.SetModes':
state = {load: params.updateModeSettings.load};
ref = firebaseRef.child(deviceId).child('Modes');
break;
// Add SetToggles command
case 'action.devices.commands.SetToggles':
state = {Turbo: params.updateToggleSettings.Turbo};
ref = firebaseRef.child(deviceId).child('Toggles');
break;
}
Aktualizowanie odpowiedzi funkcji QUERY
Na koniec musisz zaktualizować odpowiedź QUERY
, aby zgłosić tryb turbo pralki. Dodaj zaktualizowane zmiany do funkcji queryFirebase
i queryDevice
, aby uzyskać stan przełącznika zgodnie z danymi przechowywanymi w bazie danych w czasie rzeczywistym.
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,
load: snapshotVal.Modes.load,
// Add Toggles snapshot
Turbo: snapshotVal.Toggles.Turbo,
};
}
const queryDevice = async (deviceId) => {
const data = queryFirebase(deviceId);
return {
on: data.on,
isPaused: data.isPaused,
isRunning: data.isRunning,
currentRunCycle: [{ ... }],
currentTotalRemainingTime: 1212,
currentCycleRemainingTime: 301,
currentModeSettings: {
load: data.load,
},
// Add currentToggleSettings
currentToggleSettings: {
Turbo: data.Turbo,
},
};
};
Aktualizowanie stanu raportu
Na koniec zaktualizuj funkcję reportstate
, aby przekazywała do Home Graph informacje o tym, czy pralka jest ustawiona na tryb turbo.
index.js
const requestBody = {
requestId: 'ff36a3cc', /* Any unique ID */
agentUserId: USER_ID,
payload: {
devices: {
states: {
/* Report the current state of your washer */
[context.params.deviceId]: {
on: snapshot.OnOff.on,
isPaused: snapshot.StartStop.isPaused,
isRunning: snapshot.StartStop.isRunning,
currentModeSettings: {
load: snapshot.Modes.load,
},
// Add currentToggleSettings
currentToggleSettings: {
Turbo: snapshot.Toggles.Turbo,
},
},
},
},
},
};
Wdrażanie w Firebase
Aby wdrożyć zaktualizowane funkcje, uruchom to polecenie:
firebase deploy --only functions
Po zakończeniu wdrażania kliknij przycisk Odśwież w interfejsie internetowym, aby wywołać synchronizację żądań.
Możesz teraz wydać polecenie, aby pralka przeszła w tryb turbo, mówiąc:
„OK Google, włącz turbo w pralce”
Możesz też sprawdzić, czy pralka jest już w trybie turbo, pytając:
„OK Google, czy moja pralka jest w trybie turbo?”
6. Zgłaszanie błędów i wyjątków
Obsługa błędów w ramach integracji chmur umożliwia zgłaszanie użytkownikom problemów, które powodują niepowodzenie odpowiedzi EXECUTE
i QUERY
. Powiadomienia zwiększają wygodę użytkowników podczas interakcji z urządzeniem inteligentnym i integracją.
W przypadku niepowodzenia żądania EXECUTE
lub QUERY
integracja powinna zwrócić kod błędu. Jeśli na przykład chcesz wywołać błąd, gdy użytkownik spróbuje uruchomić pralkę z otwartą pokrywą, odpowiedź EXECUTE
będzie wyglądać tak:
{
"requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
"payload": {
"commands": [
{
"ids": [
"456"
],
"status": "ERROR",
"errorCode": "deviceLidOpen"
}
]
}
}
Teraz, gdy użytkownik poprosi o włączenie pralki, Asystent odpowie:
„Pokrywa pralki jest otwarta. Zamknij ją i spróbuj ponownie”.
Wyjątki są podobne do błędów, ale wskazują, kiedy alert jest powiązany z poleceniem, co może blokować jego wykonanie. Wyjątek może zawierać powiązane informacje za pomocą atrybutu StatusReport
, takiego jak poziom naładowania baterii lub ostatni stan. Kody wyjątku nieblokującego są zwracane z kodem stanu SUCCESS
, a kody wyjątku blokującego – z kodem stanu EXCEPTIONS
.
Przykład odpowiedzi z wyjątkiem znajduje się w tym fragmencie kodu:
{
"requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
"payload": {
"commands": [{
"ids": ["123"],
"status": "SUCCESS",
"states": {
"online": true,
"isPaused": false,
"isRunning": false,
"exceptionCode": "runCycleFinished"
}
}]
}
}
Asystent odpowiada:
„Pralka skończyła pracę”.
Aby dodać raportowanie błędów dla pralki, otwórz functions/index.js
i dodaj definicję klasy błędów, jak pokazano w tym fragmencie kodu:
index.js
app.onQuery(async (body) => {...});
// Add SmartHome error handling
class SmartHomeError extends Error {
constructor(errorCode, message) {
super(message);
this.name = this.constructor.name;
this.errorCode = errorCode;
}
}
Zaktualizuj odpowiedź na wykonanie, aby zwrócić kod błędu i stan błędu:
index.js
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) => {
...
})
//Add error response handling
.catch((error) => {
functions.logger.error('EXECUTE', device.id, error);
result.ids.push(device.id);
if (error instanceof SmartHomeError) {
result.status = 'ERROR';
result.errorCode = error.errorCode;
}
})
);
}
}
}
Asystent może teraz poinformować użytkowników o dowolnym kodzie błędu, który został zgłoszony. W następnej sekcji znajdziesz konkretny przykład.
7. Dodawanie dodatkowej weryfikacji użytkownika
Jeśli Twoje urządzenie ma tryby, które wymagają zabezpieczenia lub powinny być ograniczone do określonej grupy autoryzowanych użytkowników, takich jak aktualizacja oprogramowania lub odblokowanie blokady, w ramach integracji należy wdrożyć dodatk weryfikujący użytkownika.
Możesz wdrożyć dodatkową weryfikację użytkownika na wszystkich typach i cechach urządzeń, dostosowując ustawienia tak, aby wyzwanie bezpieczeństwa było wyświetlane za każdym razem lub aby spełnianie określonych kryteriów było wymagane.
No
challenge
– żądanie i odpowiedź, które nie używają testu uwierzytelniania (jest to zachowanie domyślne)ackNeeded
– dodatkowa weryfikacja użytkownika, która wymaga wyraźnego potwierdzenia (tak lub nie).pinNeeded
– dodatkowa weryfikacja użytkownika, która wymaga podania osobistego numeru identyfikacyjnego (PIN)
W tym ćwiczeniu dodaj do polecenia włączania pralki wyzwanie ackNeeded
, a także funkcję zwracającą błąd, jeśli nie uda się przeprowadzić weryfikacji dodatkowej.
Otwórz functions/index.js
i dodaj definicję klasy błędów, która zwraca kod błędu i typ wyzwania, jak w tym fragmencie kodu:
index.js
class SmartHomeError extends Error { ... }
// Add secondary user verification error handling
class ChallengeNeededError extends SmartHomeError {
/**
* Create a new ChallengeNeededError
* @param {string} suvType secondary user verification challenge type
*/
constructor(suvType) {
super('challengeNeeded', suvType);
this.suvType = suvType;
}
}
Musisz też zaktualizować odpowiedź na wykonanie, aby zwracać błąd challengeNeeded
w ten sposób:
index.js
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) => {
...
})
.catch((error) => {
functions.logger.error('EXECUTE', device.id, error);
result.ids.push(device.id);
if (error instanceof SmartHomeError) {
result.status = 'ERROR';
result.errorCode = error.errorCode;
//Add error response handling
if (error instanceof ChallengeNeededError) {
result.challengeNeeded = {
type: error.suvType
};
}
}
})
);
}
}
}
Na koniec zmodyfikuj updateDevice
, aby wymagać wyraźnego potwierdzenia włączenia lub wyłączenia pralki.
index.js
const updateDevice = async (execution,deviceId) => {
const {challenge,params,command} = execution; //Add secondary user challenge
let state, ref;
switch (command) {
case 'action.devices.commands.OnOff':
//Add secondary user verification challenge
if (!challenge || !challenge.ack) {
throw new ChallengeNeededError('ackNeeded');
}
state = {on: params.on};
ref = firebaseRef.child(deviceId).child('OnOff');
break;
...
}
return ref.update(state)
.then(() => state);
};
Wdrażanie w Firebase
Aby wdrożyć zaktualizowaną funkcję, uruchom to polecenie:
firebase deploy --only functions
Po wdrożeniu zaktualizowanego kodu musisz potwierdzić polecenie głosowo, gdy poprosisz Asystenta o włączenie lub wyłączenie pralki. Przykład:
Ty: „OK Google, włącz pralkę”
Asystent: „Czy na pewno chcesz włączyć pralkę?”
Ty: „Tak”.
Szczegółowe odpowiedzi na poszczególne etapy weryfikacji dodatkowej użytkownika możesz też sprawdzić, otwierając logi Firebase.
8. Gratulacje
Gratulacje! Rozszerzyliśmy funkcje integracji między chmurami za pomocą atrybutów Modes
i Toggles
oraz zabezpieczyliśmy ich wykonywanie za pomocą dodatkowej weryfikacji użytkownika.
Więcej informacji
Oto kilka pomysłów, które możesz wdrożyć, aby uzyskać więcej informacji:
- Dodaj na urządzeniach funkcje wykonania lokalnego.
- Aby zmienić stan urządzenia, użyj innego typu weryfikacji dodatkowej użytkownika.
- Zaktualizuj odpowiedź na zapytanie QUERY dotyczące cechy
RunCycle
, aby aktualizować ją dynamicznie. - Zapoznaj się z tym przykładem na GitHubie.