Do interfejsów API urządzeń można uzyskać dostęp za pomocą interfejsów API Home. Zaimportuj do aplikacji te pakiety:
import com.google.home.Home
import com.google.home.HomeDevice
import com.google.home.Id
Aby używać określonych typów urządzeń lub ich cech z interfejsami Device API, musisz je zaimportować osobno.
Aby na przykład używać atrybutu Matter Włączanie/wyłączanie i typu urządzenia Wtyczka, zaimportuj do aplikacji te pakiety:
import com.google.home.matter.standard.OnOff
import com.google.home.matter.standard.OnOffPluginUnitDevice
Więcej informacji znajdziesz w artykule Model danych.
Obsługa błędów
Każda metoda w interfejsach API Home może wywołać błądHomeException
, dlatego zalecamy użycie bloku try-catch
, aby przechwytywać błądHomeException
we wszystkich wywołaniach.
Podczas obsługi HomeException
sprawdź pola code
i message
, aby dowiedzieć się, co poszło nie tak.
Każdy nieobsługiwany wyjątek spowoduje awarię aplikacji.
Więcej informacji znajdziesz w artykule Postępowanie z błędami.
Przykładowo, aby wysłać polecenie do urządzenia, zobacz artykuł Wysyłanie polecenia do urządzenia.
Przykładowe rozmowy
Pobieranie listy urządzeń
Jeśli struktura jest dostępna, wywołanie devices()
zwraca listę urządzeń Flow, do których masz dostęp w ramach tej struktury:
// Get a flow of all devices accessible to the user val allDevicesFlow: HomeObjectsFlow<HomeDevice> = home.devices() // Calling list() on a HomeObjectsFlow returns the first Set of elements. val allDevices: Set<HomeDevice> = allDevicesFlow.list()
W tym miejscu można uzyskać dostęp do stanów poszczególnych urządzeń i wysłać do nich obsługiwane polecenia.
Czytanie stanu urządzenia
Zobaczmy przykład sprawdzania atrybutu OnOff
z cechy Wł./wył. urządzenia. Korzystając z modelu danych cech interfejsów API Home, w którym ta cecha jest identyfikowana jako OnOff
, możesz pobierać dane cech za pomocą klasy standardTraits
typu urządzenia:
// Assuming we have a device. val deviceFlow = home.devices().itemFlow(myDeviceId) val device = deviceFlow.first() // Get a flow of a standard trait on the type. distinctUntilChanged() is needed to only trigger // on the specific trait changes and not the whole type. val onOffTraitFlow: Flow<OnOff?> = device.type(DimmableLightDevice).map { it.standardTraits.onOff }.distinctUntilChanged() val onOffTrait: OnOff = onOffTraitFlow.first()!!
Aby dowiedzieć się więcej o funkcji przepływu w Kotlinie, zapoznaj się z artykułem distinctUntilChanged
.
Unieważnianie stanu w subskrypcji cech
Interfejs TraitStateInvalidation
umożliwia unieważnienie stanu wyodrębnionego za pomocą subskrypcji na urządzeniu docelowym w przypadku, gdy stan nie jest zgłaszany prawidłowo.
Przykłady sytuacji, w których stan może nie być prawidłowo zgłaszany, to m.in. użycie atrybutów w cechach Matter o jakości „C” lub nieoczekiwane problemy spowodowane implementacją urządzenia.
Ten interfejs API wykonuje wymuszone odczytanie bieżącego stanu atrybutu i zwraca wynik za pomocą istniejących przepływów atrybutów.
Pobierz cechę, a potem uruchom na niej funkcję forceRead
:
val generalDiagnosticsTrait = device.trait(GeneralDiagnostics).first()
generalDiagnosticsTrait.forceRead()
Pobieranie listy cech typu urządzenia
Typy urządzeń powinny być używane jako punkt wejścia do odczytu cech, ponieważ dzielą urządzenie na elementy funkcjonalne (np. punkty końcowe w Matter).
Uwzględniają one też kolizje cech w przypadku, gdy urządzenie ma 2 typy urządzeń, z których każdy może mieć tę samą cechę. Jeśli na przykład urządzenie jest jednocześnie głośnikiem i ściemnianym światłem, ma 2 cechy włączania/wyłączania i 2 cechy regulacji poziomu.
Aby uzyskać listę dostępnych cech dla typu urządzenia „Zgaś światło”:
// Get all types available on this device. Requires the types to be part of the registry during // SDK initialization. val typesFlow: Flow<Set<DeviceType>> = device.types() // Get a snapshot of all types. val types: Set<DeviceType> = typesFlow.first() // Get the DimmableLightDevice instance from the set of types. val dimmableLightDevice = types.filterIsInstance<DimmableLightDevice>().firstOrNull() // Get all traits in the type + traits registered val allTraits: Set<Trait> = dimmableLightDevice!!.traits()
Inny rodzaj kolizji cech może wystąpić, gdy urządzenie ma 2 cechy o tej samej nazwie. Na przykład onOff
może odnosić się do standardowego atrybutu OnOff
lub do atrybutu zdefiniowanego przez producenta OnOff
. Aby uniknąć potencjalnych niejasności dotyczących tego, która cecha jest zamierzona, instancja Trait
odwołująca się do urządzenia powinna być poprzedzona odpowiednią przestrzenią nazw. W przypadku standardowych cech, czyli takich, które są analogiczne do standardowych klastrów Matter, użyj standardTraits
. W przypadku cech Google użyj googleTraits
:
// Accessing standard traits on the type. val onOffTrait: OnOff? = dimmableLightDevice.standardTraits.onOff val levelControlTrait: LevelControl? = dimmableLightDevice.standardTraits.levelControl
Aby uzyskać dostęp do cechy producenta, odwołuj się do niej bezpośrednio:
// Accessing a custom trait on the type. val customTrait = dimmableLightDevice.trait(MyCustomTrait)
Pobieranie listy urządzeń z określonym atrybutem
Funkcji filter
w Kotlinie można używać do dalszego dopracowywania wywołań interfejsu API. Aby na przykład uzyskać listę urządzeń w domu, które mają cechę włączania i wyłączania:
// Get all devices that support OnOff val onOffDevices: Flow<List<HomeDevice>> = home.devices().map { devices -> devices.filter { it.has(OnOff) } }
Pełna lista cech dostępnych w interfejsie Trait
.
Pobieranie listy urządzeń o podobnych typach
Aby zobaczyć listę urządzeń odpowiadających wszystkim lampom w domu:
// Get a list of devices with similar device types (lights) val lightDevices = home.devices().map { devices -> devices.filter { it.has(DimmableLightDevice) || it.has(OnOffLightDevice) || it.has(ColorTemperatureLightDevice) || it.has(ExtendedColorLightDevice) } }
Interfejsy API Home obsługują kilka typów urządzeń, które mogą reprezentować podstawowy typ urządzenia. Na przykład nie ma typu urządzenia „Światło”. Zamiast tego, jak w poprzednim przykładzie, lampka może być reprezentowana przez 4 różne typy urządzeń. Aby uzyskać pełny obraz typu urządzenia na wyższym poziomie w domu, w przefiltrowanych przepływach danych musisz uwzględnić wiele typów urządzeń.
Pełną listę typów urządzeń dostępnych w interfejsie DeviceType
znajdziesz w interfejsie API Home.
Pobieranie identyfikatora producenta lub identyfikatora produktu urządzenia
Cecha BasicInformation
zawiera informacje takie jak identyfikator dostawcy, identyfikator produktu, nazwa produktu i numer seryjny urządzenia:
// Get device basic information. All general information traits are on the RootNodeDevice type. val basicInformation = device.type(RootNodeDevice).first().standardTraits.basicInformation!! println("vendorName ${basicInformation.vendorName}") println("vendorId ${basicInformation.vendorId}") println("productId ${basicInformation.productId}")
Identyfikowanie urządzeń w chmurze
Jeśli jesteś producentem urządzeń i tworzysz urządzenia Cloud-to-cloud, aby zidentyfikować swoje urządzenia Cloud-to-cloud za pomocą atrybutu BasicInformation
, możesz uwzględnić te pola ciągu znaków w odpowiedzi SYNC
:
Identyfikator dostawcy wydany przez Connectivity Standards Alliance (CSA):
"matterOriginalVendorId": "0xfff1",
Identyfikator produktu, który jednoznacznie identyfikuje produkt danego sprzedawcy:
"matterOriginalProductId": "0x1234",
Unikalny identyfikator urządzenia, który jest tworzony w sposób specyficzny dla producenta:
"matterUniqueId": "matter-device-id",
Podczas wypełniania tych pól tekstowych użyj Matteridentyfikatorów sprzedawcy i produktu, jeśli je masz. Jeśli nie jesteś członkiem CSA i nie masz przypisanych tych identyfikatorów, możesz pozostawić pola matterOriginalVendorId
i matterOriginalProductId
puste i podać identyfikator matterUniqueId
.
Przykładowa odpowiedź SYNC pokazuje użycie tych pól:
{
"requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
"payload": {
"agentUserId": "1836.15267389",
"devices": [
{
"id": "456",
"type": "action.devices.types.LIGHT",
"traits": [
"action.devices.traits.OnOff",
"action.devices.traits.Brightness",
"action.devices.traits.ColorSetting",
],
"willReportState": true,
"deviceInfo": { ... },
"matterOriginalVendorId": "0xfff1",
"matterOriginalProductId": "0x1234",
"matterUniqueId": "matter-device-id",
"otherDeviceIds": [
{
"deviceId": "local-device-id",
}
]
}
]
}
}
Więcej informacji znajdziesz w dokumentacji Cloud-to-cloud SYNC
.
Metadane urządzenia i cechy
Urządzenia i cechy w interfejsach Home API są powiązane z metadanymi, które mogą ułatwiać zarządzanie wrażeniami użytkownika w aplikacji.
Każda cecha w interfejsach API Home zawiera właściwość sourceConnectivity
, która zawiera informacje o stanie online i lokalizacji cechy (przekierowanie lokalne lub zdalne).
Pobieranie głównego typu urządzenia
Niektóre urządzenia mogą wyświetlać wiele typów urządzeń za pomocą interfejsów API Home. Aby mieć pewność, że użytkownicy zobaczą odpowiednie opcje aplikacji (np. kontrolę urządzenia i sugerowane automatyzacje) na swoich urządzeniach, warto sprawdzić, jaki jest podstawowy typ urządzenia.
Najpierw pobierz typy urządzenia za pomocą elementu type()
, a następnie określ, który z nich jest podstawowy:
val types = device.types().first() val primaryType = types.first { it.metadata.isPrimaryType }
Sprawdzanie, czy cecha jest dostępna online
Aby sprawdzić łączność cechy, użyj metody connectivityState()
:
val onOffConnectivity = onOffTrait?.metadata?.sourceConnectivity?.connectivityState
Niektóre cechy, zazwyczaj cechy Google smart home, mogą być wyświetlane w trybie offline, jeśli urządzenie nie ma połączenia z internetem. Dzieje się tak, ponieważ te cechy są oparte na chmurze i nie mają routingu lokalnego.
Sprawdzanie połączenia urządzenia
Łączność urządzenia jest sprawdzana na poziomie typu urządzenia, ponieważ niektóre urządzenia obsługują wiele typów urządzeń. Zwrócony stan to kombinacja stanów połączeń wszystkich cech na tym urządzeniu.
val lightConnectivity = dimmableLightDevice.metadata.sourceConnectivity.connectivityState
Stan PARTIALLY_ONLINE
może wystąpić w przypadku mieszanych typów urządzeń, gdy nie ma połączenia z internetem. Atrybuty standardu Matter mogą być nadal dostępne online z powodu routingu lokalnego, ale atrybuty oparte na chmurze będą offline.
Sprawdzanie kierowania sieciowego cechy
Lokalizacja atrybutu jest też dostępna w interfejsach API Home. dataSourceLocality
wskazuje, czy cecha jest kierowana zdalnie (przez chmurę), lokalnie (przez lokalny koncentrator) czy peer-to-peer (bezpośrednio z urządzenia na urządzenie, bez koncentratora).
Wartość lokalizacji nieznanej UNSPECIFIED
może wystąpić np. podczas uruchamiania aplikacji, która jeszcze nie połączyła się z hubem lub serwerem. Te urządzenia są niedostępne i nie będą reagować na żądania interakcji z poleceń ani zdarzeń. To klient decyduje, jak ma postępować z takimi urządzeniami.
val onOffLocality = onOffTrait?.metadata?.sourceConnectivity?.dataSourceLocality
Sprawdzanie trasowania sieci na urządzeniu
Podobnie jak w przypadku łączności, lokalizacja jest sprawdzana na poziomie typu urządzenia. Zwrócony stan to kombinacja lokalizacji wszystkich cech na danym urządzeniu.
val lightLocality = dimmableLightDevice.metadata.sourceConnectivity.dataSourceLocality
Stan MIXED
może być obserwowany w podobnym scenariuszu jak w przypadku łączności PARTIALLY_ONLINE
: niektóre cechy są oparte na chmurze, a inne na lokalnych zasobach.
Lista interfejsów API
Po utworzeniu instancji interfejsu Home
można korzystać z tych interfejsów API urządzenia:
Interfejs API | Opis |
---|---|
devices() |
Uzyskaj dostęp do wszystkich urządzeń we wszystkich strukturach na koncie Google. Zwraca HomeObjectsFlow , który zawiera dalsze opcje wyszukiwania i filtrowania. |
Gdy masz konto HomeDevice
, możesz korzystać z tych interfejsów API:
Interfejs API | Opis |
---|---|
allCandidates() |
Zwraca wszystkie kandydatury automatyzacji dla urządzenia i jego elementów podrzędnych. |
candidates() |
Zwraca wszystkie kandydatury automatyzacji dla urządzenia. |
connectivityStateChanged |
Ostatni czas zmiany stanu urządzenia. |
events(event) |
Pobiera przepływ danych konkretnego zdarzenia. |
events(trait) |
Pobiera przepływ wszystkich zdarzeń według tej cechy. |
events(traits) |
Pobiera przepływ wszystkich zdarzeń według tych atrybutów. |
getSourceConnectivity(trait) |
Pobiera metadane dotyczące określonej cechy. Zwraca wartość SourceConnectivity . |
has(trait) |
Sprawdź, czy urządzenie obsługuje aktualnie żądaną cechę. |
has(type) |
czy urządzenie obsługuje podany typ. |
id |
Unikalny identyfikator systemu urządzenia. |
isInRoom |
czy urządzenie znajduje się w pokoju. |
isInStructure |
czy urządzenie znajduje się w strukturze. |
isMatterDevice |
Jeśli urządzenie jest obsługiwane przez Matter. |
name |
Nazwa urządzenia podana przez użytkownika. |
room() |
Sala, do której jest przypisane urządzenie. Zwraca wartość Room . |
roomId |
Identyfikator pokoju, do którego przypisana jest kamera. Zwraca wartość Id . |
sourceConnectivity |
Łączność źródłowa urządzenia, która reprezentuje zbiorcze stany łączności i lokalizację sieciową cech urządzenia. |
structure() |
Struktura, do której jest przypisane urządzenie. Zwraca wartość Structure . |
structureId |
Identyfikator struktury, do której przypisany jest dany sprzęt. Zwraca wartość Id . |
type(type) |
Pobierz definicję typu z wypełnionymi cechami (jeśli są dostępne) w celu uzyskania bezpośredniego dostępu. Zawsze zwraca aktualny zrzut cech. |
types() |
wyświetlić listę wszystkich typów dostępnych na urządzeniu; |