Trzy elementy, jeden cel
Od strony technicznej Timmy jest zbudowany całkiem praktycznie: Flutter do aplikacji, WebRTC do dźwięku i obrazu w czasie rzeczywistym oraz Firebase do koordynacji. Nie chciałem budować wielkiej platformy, która przepuszcza wszystko przez chmurę. Każdy element powinien wiedzieć jak najmniej, a jednocześnie niezawodnie współpracować z pozostałymi.
WebRTC: bezpośrednie połączenie, domyślnie szyfrowane
WebRTC (Web Real-Time Communication) przesyła dźwięk i obraz między urządzeniem dziecka a urządzeniem rodzica. W najlepszym przypadku dane płyną bezpośrednio między dwoma urządzeniami, w modelu peer-to-peer, bez serwera mediów pośrodku.
Każde połączenie WebRTC domyślnie używa DTLS-SRTP. Jeśli ktoś przechwyci pakiety sieciowe, nie uzyska czytelnego dźwięku ani obrazu. To szyfrowanie jest częścią protokołu i w WebRTC nie można go po prostu wyłączyć.
To było dla mnie najważniejsze: dane z pokoju dziecka nie powinny trafiać na mój serwer. Pozostają między twoimi urządzeniami.
Sygnalizacja przez Firebase Firestore
Zanim WebRTC wystartuje, urządzenia muszą się odnaleźć i uzgodnić sposób połączenia. Ta część nazywa się sygnalizacją. Timmy używa do tego Firebase Firestore, chmurowej bazy danych Google.
Wymieniane są wyłącznie techniczne dane połączenia:
- Oferty i odpowiedzi SDP: Opisują możliwości urządzeń (obsługiwane kodeki, rozdzielczości itp.).
- Kandydaci ICE: Możliwe ścieżki sieciowe, przez które urządzenia mogą się ze sobą połączyć.
Dźwięk i obraz nie trafiają do Firebase. Firestore przesyła jedynie techniczne dane połączenia. Timmy szyfruje też tę warstwę sygnalizacji, więc Firestore nie staje się miejscem, gdzie SDP i ICE są dostępne w postaci zwykłego tekstu.
Serwery TURN: gdy bezpośrednia ścieżka nie działa
Niektóre sieci blokują bezpośrednie połączenia, na przykład restrykcyjne zapory sieciowe lub niektórzy operatorzy komórkowi. Wtedy WebRTC potrzebuje przekaźnika TURN (Traversal Using Relays around NAT).
Timmy najpierw próbuje użyć lokalnego serwera TURN, a gdy lokalny przekaźnik jest niedostępny lub przeciążony, korzysta awaryjnie z Cloudflare. Przekaźnik przekazuje zaszyfrowane pakiety. Nie otrzymuje kluczy do dźwięku ani obrazu — szyfrowanie WebRTC pozostaje nienaruszone.
Dane uwierzytelniające TURN pochodzą z funkcji Firebase Cloud Function i są ważne tylko przez 24 godziny. Stałe dane uwierzytelniające w aplikacji niani elektronicznej byłyby moim zdaniem zbyt ryzykowne.
Nearby Connections: urządzenia odnajdują się automatycznie
Aby uniknąć uciążliwych kroków konfiguracji między urządzeniem dziecka a urządzeniem rodzica, Timmy używa Nearby Connections. Google udostępnia tę warstwę wykrywania przez Bluetooth i Wi‑Fi.
Automatyczne parowanie w Timmy działa bez ręcznego wpisywania kodu: urządzenia wykrywają się nawzajem i znajdują to samo miejsce wymiany kluczy. Jeśli się to nie uda, możesz wpisać 4-znakowy kod. Kod parowania nigdy nie opuszcza urządzenia; Firestore widzi jedynie kryptograficzny skrót (SHA-256) jako identyfikator dokumentu.
Anonimowe uwierzytelnianie
Timmy korzysta z anonimowego uwierzytelniania Firebase. Przy pierwszym uruchomieniu każde urządzenie otrzymuje tymczasowy, anonimowy identyfikator. Nie ma konta, adresu e-mail ani hasła. Identyfikator służy wyłącznie do egzekwowania reguł Firestore: tylko uwierzytelnione urządzenia mogą odczytywać lub zapisywać dane sesji.
Architektura: kto wysyła, kto odbiera
Timmy ma dwa tryby:
- Tryb dziecka (nadajnik): Urządzenie rejestruje dźwięk przez mikrofon i wysyła go do urządzenia rodzica przez WebRTC. Opcjonalnie można włączyć kamerę; obraz jest wtedy również przesyłany bezpośrednio.
- Tryb rodzica (odbiornik): Urządzenie odbiera dźwięk i obraz, wyświetla podgląd z kamery oraz umożliwia krótkie komunikaty głosowe do urządzenia dziecka za pomocą funkcji naciśnij i mów.
Sterowanie, takie jak funkcja naciśnij i mów oraz włączanie i wyłączanie kamery, wykorzystuje DataChannel, kolejny kanał WebRTC, który wysyła małe zaszyfrowane wiadomości bezpośrednio między urządzeniami.
Dlaczego Flutter?
Flutter to framework Google do tworzenia aplikacji na wiele platform. Dla Timmy oznacza to, że mogę napisać dużą część logiki raz i używać jej na Androidzie oraz iOS. Timmy jest dostępny na Androidzie, a wersja na iOS jest bliska premiery. Mniej powielonego kodu to mniej miejsc, w których mogą pojawić się błędy.
Podsumowanie
Zasada techniczna jest prosta: Timmy powinien przetwarzać tylko dane, których naprawdę potrzebuje. WebRTC chroni multimedia, Firebase koordynuje konfigurację połączenia, TURN widzi wyłącznie zaszyfrowane pakiety, a Nearby Connections upraszcza parowanie.
Dobra technologia trochę znika w codziennym życiu. Po prostu działa, nie zamieniając pokoju dziecka w projekt chmurowy.