%20Using%20RPC.png?inst-v=8eb5b645-f616-454e-a1eb-47030b06b1ec)
Przegląd
Bluetooth Low Energy (BLE) stał się kluczową technologią komunikacji bezprzewodowej w nowoczesnych urządzeniach inteligentnych, oferując efektywne i energooszczędne łącze. Urządzenia Shelly, będące częścią ekosystemów smart home, wykorzystują BLE do umożliwienia płynnej komunikacji i sterowania. Istotnym elementem komunikacji BLE w Shelly jest implementacja protokołów Remote Procedure Call (RPC) nad BLE, co pozwala na zaawansowane interakcje między urządzeniami a kontrolerami. Ten artykuł zagłębia się w techniczne niuanse komunikacji z urządzeniami Shelly przy użyciu BLE, koncentrując się na Generic Attribute Profile (GATT), identyfikatorach oraz mechanizmach wykonywania operacji RPC typu odczyt i zapis.
Wymagania wstępne
Zanim przejdziesz do technicznych aspektów komunikacji z urządzeniami Shelly przez BLE i RPC, ważne jest podstawowe zrozumienie następujących koncepcji:
Bluetooth Low Energy (BLE): Technologia sieci osobistej bezprzewodowej zaprojektowana pod kątem niskiego poboru energii i kosztów. BLE jest szeroko stosowane w urządzeniach IoT do efektywnej komunikacji.
Generic Attribute Profile (GATT): Protokół BLE, który definiuje, jak dane są strukturyzowane i wymieniane między urządzeniami. GATT organizuje dane w usługi i charakterystyki.
Remote Procedure Call (RPC): Protokół, który pozwala programowi wywołać procedurę (podprogram) na zdalnym urządzeniu tak, jakby była lokalnym wywołaniem.
JSON: Lekki format wymiany danych używany do strukturyzowania żądań i odpowiedzi RPC.
Architektura BLE RPC w Shelly
Komunikacja z urządzeniami Shelly przez BLE i RPC obejmuje płynne przejście od nawiązania połączenia, przez interakcję z konkretnymi usługami i charakterystykami GATT, po konstruowanie i wysyłanie żądań RPC oraz odbieranie i parsowanie odpowiedzi. Ten zunifikowany proces zapewnia wydajną i niezawodną komunikację z urządzeniami Shelly, umożliwiając różnorodne integracje w różnych systemach i językach programowania.
Kluczowe komponenty GATT w urządzeniach Shelly
Shelly GATT Service UUID: Identyfikuje główną usługę odpowiedzialną za komunikację RPC.
SHELLY_GATT_SERVICE_UUID = "5f6d4f53-5f52-5043-5f53-56435f49445f" RPC Data Characteristic UUID: Obsługuje przesyłanie danych żądań i odpowiedzi RPC.
RPC_CHAR_DATA_UUID = "5f6d4f53-5f52-5043-5f64-6174615f5f5f" RPC TX Control Characteristic UUID: Zarządza kontrolą transmisji, w szczególności wysyłaniem informacji o długości danych do urządzenia Shelly.
RPC_CHAR_TX_CTL_UUID = "5f6d4f53-5f52-5043-5f74-785f63746c5f" RPC RX Control Characteristic UUID: Obsługuje kontrolę odbioru, głównie odbieranie informacji o długości danych z urządzenia Shelly.
RPC_CHAR_RX_CTL_UUID = "5f6d4f53-5f52-5043-5f72-785f63746c5f" Uwaga: Te UUID są specyficzne dla urządzeń Shelly — odwołaj się do oficjalnej dokumentacji Shelly lub użyj narzędzi do skanowania BLE, aby zidentyfikować właściwe UUID.
Kluczowe aspekty RPC Shelly przez BLE
Protokół JSON-RPC 2.0
Urządzenia Shelly Gen2+ korzystają z protokołu JSON-RPC 2.0 do monitorowania i sterowania funkcjami. Protokół ten jest symetryczny, pozwalając obydwu stronom — klientowi i urządzeniu — wywoływać metody i wysyłać powiadomienia do siebie nawzajem. JSON-RPC 2.0 zapewnia ustrukturyzowaną i ustandaryzowaną komunikację, ułatwiając niezawodne interakcje między aplikacją kliencką a urządzeniem Shelly.
Konwencje przestrzeni nazw
Shelly porządkuje swoje metody RPC w przestrzenie nazw w celu kategoryzacji funkcji, co poprawia przejrzystość i utrzymanie. Poniżej znajdują się niektóre główne przestrzenie nazw i przykładowe metody:
-
Przestrzeń nazw Shelly: Obsługuje zarządzanie systemem, konfigurację i status.
Shelly.FactoryReset
Shelly.ResetWiFiConfig
Shelly.ListTimezones
-
Przestrzeń nazw Switch: Zarządza dyskretnymi wyjściami zasilania, zazwyczaj przekaźnikami.
Switch.Set
Switch.GetConfig
Uwaga: Powyższe przestrzenie nazw i metody są przykładami. Implementacja RPC Shelly obejmuje liczne dodatkowe metody w różnych przestrzeniach nazw, aby wspierać różnorodne funkcje urządzeń.
Typy ramek
Komunikacja między użytkownikiem a urządzeniem składa się z trzech typów ramek:
Ramka żądania: Służy do wysyłania poleceń do urządzeń.
Ramka odpowiedzi: Służy do otrzymywania odpowiedzi od urządzeń.
Ramka powiadomienia: Służy do otrzymywania niezamówionych aktualizacji od urządzeń.
Struktury ramek w protokole RPC Shelly
Ramka żądania
Ramka żądania to obiekt JSON używany do wywoływania metod na urządzeniach Shelly. Zawiera następujące atrybuty:
jsonrpc (string): Określa wersję używanego JSON-RPC, zwykle "2.0". To pole może być pominięte.
id (number or string): Identyfikator żądania, używany do powiązania ramki odpowiedzi. Wymagane.
src (string): Nazwa źródła żądania (np. "user_1"). Wymagane.
method (string): Nazwa procedury do wywołania (np. "Shelly.GetDeviceInfo"). Wymagane.
params (object): Parametry przyjmowane przez metodę (np. {"id":1}). Opcjonalne.
Ramka odpowiedzi
Ramka odpowiedzi to obiekt JSON zwracany przez urządzenie Shelly w odpowiedzi na ramkę żądania. Zawiera następujące atrybuty:
id (number or string): Identyfikator komunikacji. Wymagane.
src (string): Nazwa źródła odpowiedzi (zwykle urządzenie Shelly). Wymagane.
dst (string): Nazwa miejsca docelowego (zwykle żądający). Wymagane.
result (object): Wynik wywołanej procedury, jeśli żądanie zakończyło się sukcesem. Wyklucza się nawzajem z polem error.
error (object): Zawiera opis błędu, który wystąpił, jeśli żądanie nie powiodło się. Wyklucza się nawzajem z polem result.
Ramka powiadomienia
Ramka powiadomienia to obiekt JSON wysyłany przez urządzenie Shelly, aby powiadomić klienta o pewnych zdarzeniach lub zmianach statusu bez oczekiwania odpowiedzi. Zawiera następujące atrybuty:
src (string): Nazwa źródła powiadomienia (np. urządzenie Shelly). Wymagane.
dst (string): Nazwa miejsca docelowego (np. "user_1"). Wymagane.
method (string): Wywoływana metoda (np. "NotifyStatus"). Wymagane.
params (object): Parametry powiadomienia zawierające istotne dane. Wymagane.
Krok po kroku: komunikacja z urządzeniami Shelly
1. Nawiązanie połączenia BLE
Cel: Połącz się z urządzeniem Shelly, używając jego unikalnego adresu BLE.
Proces:
Wykrywanie urządzeń: Rozpocznij skanowanie pobliskich urządzeń BLE, aby zidentyfikować urządzenie Shelly. Można to osiągnąć przy użyciu narzędzi do skanowania BLE lub bibliotek dostępnych w wybranym środowisku programistycznym. Urządzenie Shelly można zidentyfikować po nazwie lub adresie BLE.
Inicjowanie połączenia: Po zidentyfikowaniu, rozpocznij połączenie z urządzeniem Shelly używając jego adresu BLE. To połączenie stanowi podstawę dla dalszych interakcji. Upewnij się, że sprzęt BLE w Twoim systemie działa i że urządzenie Shelly jest w stanie zaakceptować połączenia.
Zagadnienia do rozważenia:
Limity czasu połączenia: Połączenia BLE mogą być niestabilne lub trwać dłużej niż oczekiwano. Zaimplementuj mechanizmy limitów czasu, aby obsłużyć scenariusze, w których próba połączenia przekracza rozsądny okres.
Logika ponownego łączenia: W przypadku niespodziewanych rozłączeń posiadanie strategii ponownego łączenia zapewnia, że aplikacja może się zregenerować bez ręcznej interwencji.
2. Interakcja z usługami i charakterystykami GATT
Cel: Uzyskać dostęp i używać konkretnych usług i charakterystyk GATT wymaganych do komunikacji RPC.
Proces:
Odkrywanie usług: Po połączeniu wykonaj odkrywanie usług, aby pobrać listę dostępnych usług GATT oferowanych przez urządzenie Shelly. Zlokalizuj usługę Shelly GATT używając jej zdefiniowanego UUID.
Odkrywanie charakterystyk: W ramach usługi Shelly GATT zidentyfikuj charakterystyki RPC Data, RPC TX Control i RPC RX Control używając ich odpowiednich UUID. Te charakterystyki są kluczowe do wysyłania żądań RPC i odbierania odpowiedzi. Odwołaj się do Kluczowe komponenty GATT w urządzeniach Shelly.
Zagadnienia do rozważenia:
Dokładność UUID: Upewnij się, że używane są poprawne UUID, aby zapobiec nieporozumieniom. Użycie błędnych UUID może prowadzić do niepowodzeń w odczycie lub zapisie do żądanych charakterystyk.
Dostępność charakterystyk: Niektóre urządzenia Shelly mogą mieć różnice w profilach GATT w zależności od modelu lub wersji firmware. Wdróż sprawdzenia potwierdzające obecność wszystkich wymaganych charakterystyk przed kontynuacją.
3. Konstruowanie żądań RPC
Cel: Tworzyć żądania RPC w poprawnym formacie, aby komunikować żądane działania do urządzenia Shelly.
Proces:
Struktura JSON: Żądania RPC są zbudowane jako obiekty JSON zawierające określone pola:
id: Unikalny identyfikator żądania, zapewniający, że odpowiedzi mogą być skorelowane z odpowiednimi żądaniami.
src: Identyfikator źródła, taki jak "user_1", wskazujący pochodzenie żądania.
method: Metoda RPC do wywołania, na przykład "Shelly.GetDeviceInfo".
params: Opcjonalne parametry wymagane przez metodę RPC.
{ "id": 123456789, "src": "user_1", "method": "Shelly.GetDeviceInfo", "params": {} } Kodowanie: Konwertuj obiekt JSON na tablicę bajtów zakodowaną w UTF-8. Ta tablica bajtów będzie przesyłana przez BLE do urządzenia Shelly.
Obliczanie długości: Określ długość w bajtach zakodowanego żądania RPC. Ta informacja o długości jest kluczowa, aby poinformować urządzenie Shelly o rozmiarze nadchodzących danych.
Pakowanie długości: Konwertuj obliczoną długość na 4-bajtową liczbę całkowitą w porządku big-endian. Ta zapakowana długość jest zapisywana do charakterystyki RPC TX Control aby zasygnalizować rozmiar nadchodzących danych.
Zagadnienia do rozważenia:
Unikalne identyfikatory żądań: Każde żądanie RPC powinno mieć unikalne id, aby dokładnie dopasować odpowiedzi do odpowiadających im żądań.
Walidacja parametrów: Upewnij się, że parametry przekazane do metody RPC są poprawne i zgodne z oczekiwanym formatem. Nieprawidłowe parametry mogą prowadzić do niepoprawnych żądań i błędów ze strony urządzenia Shelly.
4. Wysyłanie żądań RPC
Cel: Przesłać skonstruowane żądanie RPC do urządzenia Shelly przez BLE.
Proces:
Zapisz długość do charakterystyki TX Control: Zacznij od zapisania zapakowanej długości żądania RPC do charakterystyki RPC TX Control. To informuje urządzenie Shelly o rozmiarze nadchodzących danych, przygotowując je do odbioru właściwego żądania RPC.
Wprowadź krótkie opóźnienie: Po zapisaniu długości wprowadź krótkie opóźnienie (np. 1 sekunda), aby urządzenie Shelly miało czas przetworzyć informację o długości. Zapewnia to synchronizację między klientem a urządzeniem przed wysłaniem właściwych danych.
Zapisz żądanie RPC do charakterystyki Data: Następnie zapisz zakodowane bajty żądania RPC do charakterystyki RPC Data. Ta operacja wysyła właściwe polecenie lub zapytanie do urządzenia Shelly, żądając wykonania określonej metody RPC.
Zagadnienia do rozważenia:
Operacje zapisu z potwierdzeniem: Używaj operacji zapisu oczekujących odpowiedzi (acknowledgment) od urządzenia Shelly. Zapewnia to, że urządzenie pomyślnie otrzymało i przetworzyło żądanie zapisu.
Obsługa błędów: Zaimplementuj mechanizmy potwierdzające pomyślność operacji zapisu. Obsłuż scenariusze, w których zapisy nie powiodły się, możliwie z powodu problemów z połączeniem lub brakiem reakcji urządzenia, przez ponowienie próby lub powiadomienie użytkownika.
5. Odbieranie i parsowanie odpowiedzi RPC
Cel: Otrzymać odpowiedź z urządzenia Shelly, zapewniając integralność i poprawność danych.
Proces:
Odczytaj długość odpowiedzi z charakterystyki RX Control: Zacznij od odczytania długości odpowiedzi z charakterystyki RPC RX Control. Ta długość wskazuje rozmiar nadchodzących danych odpowiedzi, pozwalając klientowi wiedzieć, ile bajtów oczekiwać.
Rozpakuj długość: Konwertuj odebraną 4-bajtową liczbę całkowitą big-endian na rzeczywistą wartość długości w bajtach. Ta rozpakowana długość określa całkowity rozmiar danych odpowiedzi do odczytu.
Odczytuj dane odpowiedzi w kawałkach: Ze względu na ograniczenia MTU (Maximum Transmission Unit) BLE, odczytuj dane odpowiedzi z charakterystyki RPC Data w przystępnych kawałkach (zwykle po 20 bajtów). Kontynuuj odczytywanie, aż otrzymasz całą odpowiedź, zgodnie z wskazaną długością.
Gromadzenie danych odpowiedzi: W miarę odczytywania każdego kawałka doklejaj go do bufora lub tablicy bajtów, aby odtworzyć kompletną odpowiedź.
Dekodowanie i parsowanie odpowiedzi: Po otrzymaniu wszystkich kawałków dekoduj zebrane bajty do ciągu UTF-8 i sparsuj obiekt JSON. Ta sparsowana odpowiedź będzie zawierać albo wynik wywołania RPC, albo pole error wskazujące błąd.
Walidacja odpowiedzi: Upewnij się, że id w odpowiedzi odpowiada pierwotnemu id żądania. Ta walidacja potwierdza, że odpowiedź dotyczy właściwego żądania RPC. Dodatkowo sprawdź obecność pola result w celu potwierdzenia pomyślnego wykonania lub odpowiednio obsłuż komunikaty o błędach.
Zagadnienia do rozważenia:
Odczyty w kawałkach: Ograniczony rozmiar MTU BLE wymaga odczytywania danych w kawałkach, aby uniknąć obcięcia lub utraty danych. Zaimplementuj logikę obsługi odczytów częściowych i gromadzenia danych aż do otrzymania kompletnej odpowiedzi.
Limity czasu: Wprowadź limity czasu odczytu, aby zapobiec oczekiwaniu w nieskończoność, gdy urządzenie Shelly nie odpowie lub połączenie zostanie przerwane.
Integralność danych: Zweryfikuj, że cała odpowiedź została otrzymana i poprawnie sparsowana, aby zapewnić dokładną i niezawodną komunikację.
Radzenie sobie z typowymi wyzwaniami
Komunikacja z urządzeniami Shelly przez BLE i RPC jest potężnym podejściem, ale wiąże się z zestawem wyzwań. Skuteczne ich rozwiązanie zapewnia solidne i niezawodne integracje.
Zarządzanie rozmiarem MTU
Problem: Maksymalny rozmiar jednostki transmisyjnej (MTU) BLE definiuje maksymalny rozmiar pakietów danych, które można wysłać w jednym przesyle. Przekroczenie MTU może prowadzić do obcięcia danych lub nieudanych transmisji.
Rozwiązanie:
Odczyty/zapisy w kawałkach: Zaimplementuj logikę dzielenia dużych ładunków danych na mniejsze kawałki dostosowane do rozmiaru MTU (zwykle 20 bajtów). Zapewnia to niezawodne przesyłanie danych bez przekraczania ograniczeń BLE.
Przykładowe podejście:
Określ całkowitą długość danych do wysłania.
Podziel dane na kawałki po 20 bajtów lub mniej.
Kolejno zapisuj każdy kawałek do odpowiedniej charakterystyki.
Dynamiczna regulacja MTU: Niektóre biblioteki BLE i urządzenia wspierają negocjację większego rozmiaru MTU. Jeśli to możliwe, dostosuj MTU, aby zoptymalizować efektywność transmisji danych.
Przykładowe rozważenie:
Przed rozpoczęciem transmisji danych zażądaj większego MTU, jeśli biblioteka i urządzenie to obsługują.
Obsłuż scenariusze, w których negocjacja się nie powiedzie, wracając do standardowych rozmiarów kawałków.
Dobre praktyki:
Określ możliwości MTU: Sprawdź, czy zarówno urządzenie Shelly, jak i klient BLE obsługują większe MTU, aby zmaksymalizować przepustowość danych.
Wdroż mechanizmy zapasowe: W sytuacjach, gdy dynamiczna negocjacja MTU jest nieskuteczna, domyślnie używaj standardowych rozmiarów kawałków, aby zachować zgodność.
Limity czasu i ponawianie prób
Problem: Połączenia BLE mogą być niestabilne, prowadząc do limitów czasu lub przerw w komunikacji, szczególnie w środowiskach z zakłóceniami lub wieloma podłączonymi urządzeniami.
Rozwiązanie:
Wdrażanie limitów czasu: Ustaw odpowiednie czasy oczekiwania dla prób połączeń, operacji odczytu/zapisu i kroków przetwarzania danych. To zapobiega sytuacji, w której aplikacja czeka w nieskończoność na odpowiedzi.
Przykładowe podejście:
Zdefiniuj maksymalne czasy oczekiwania dla każdej operacji.
Jeśli operacja przekracza limit czasu, obsłuż ją łagodnie przez ponowienie próby lub powiadomienie użytkownika.
Logika ponawiania prób: Wprowadź mechanizmy ponawiania dla błędów przejściowych, takich jak tymczasowe rozłączenia czy nieudane zapisy. Ogranicz liczbę ponowień, aby uniknąć nieskończonych pętli i nadmiernego zużycia zasobów.
Przykładowe podejście:
Po nieudanej operacji odczekaj krótki okres przed ponowną próbą.
Stosuj strategie wykładniczego odwrotnego narastania (exponential backoff), aby zmniejszyć częstotliwość ponowień w czasie.
Dobre praktyki:
Wykładniczy backoff: Stopniowo zwiększaj czas oczekiwania między ponowieniami, aby zmniejszyć prawdopodobieństwo powtarzających się błędów, szczególnie w środowiskach o dużych zakłóceniach.
Powiadomienia użytkownika: Informuj użytkowników o uporczywych błędach po wyczerpaniu prób ponawiania, umożliwiając ręczną interwencję, jeśli to konieczne.
Obsługa błędów
Problem: Podczas komunikacji BLE mogą wystąpić różne błędy, w tym brak dostępności charakterystyk, niepoprawne odpowiedzi lub błędy specyficzne dla RPC.
Rozwiązanie:
Kompleksowa obsługa wyjątków: Wdróż solidne mechanizmy przechwytywania błędów na każdym etapie procesu komunikacji. Obejmuje to obsługę wyjątków związanych z BLE, błędów parsowania JSON oraz problemów specyficznych dla RPC.
Przykładowe podejście:
Opakuj krytyczne operacje w bloki try-catch.
Loguj szczegółowe komunikaty o błędach, aby ułatwić debugowanie i rozwiązywanie problemów.
Sprawdzenia walidacyjne: Wykonuj dokładne walidacje odpowiedzi, aby zapewnić integralność danych. Obejmuje to dopasowywanie identyfikatorów odpowiedzi z identyfikatorami żądań oraz weryfikację obecności oczekiwanych pól, takich jak result lub error.
Przykładowe podejście:
Po otrzymaniu odpowiedzi sprawdź, czy id zgadza się z pierwotnym żądaniem.
Upewnij się, że odpowiedź zawiera pole result lub pole error, aby określić wynik.
Dobre praktyki:
Logowanie: Prowadź szczegółowe logi wszystkich prób komunikacji, sukcesów i niepowodzeń. To pomaga w rozwiązywaniu problemów i zrozumieniu zachowania systemu w różnych warunkach.
Łagodne pogorszenie działania: W przypadku błędów niekrytycznych pozwól systemowi kontynuować działanie, obsługując awarie w sposób niezagrażający stabilności, bez przerywania innych operacji.
Podsumowanie
Komunikacja z urządzeniami Shelly przez BLE i RPC oferuje potężne możliwości tworzenia zaawansowanych integracji i rozwiązań automatyzacji w inteligentnym domu. Poprzez zrozumienie architektury BLE, usług GATT i mechanizmów RPC, deweloperzy mogą opracować solidne i wydajne ramy komunikacyjne dopasowane do swoich potrzeb. Ten przewodnik dostarczył szczegółowej mapy drogowej umożliwiającej nawiązanie płynnej komunikacji, dając Ci narzędzia do pełnego wykorzystania możliwości urządzeń Shelly w różnych językach programowania i na różnych platformach.
Cenimy Twoją opinię!
Dziękujemy za poświęcenie czasu na przeczytanie naszego artykułu! Czy był pomocny lub interesujący?
Twoje uwagi pomogą nam się poprawić. Będziemy wdzięczni za wszelkie opinie. Jeśli masz chwilę,
prosimy podziel się nimi z nami pod następującym adresem e-mail: