Skocz do zawartości

Intermediate Resource Integration System


H1M4W4R1

Pomocna odpowiedź

Podoba Ci się ten projekt? Zostaw pozytywny komentarz i daj znać autorowi, że zbudował coś fajnego!

Masz uwagi? Napisz kulturalnie co warto zmienić. Doceń pracę autora nad konstrukcją oraz opisem.

(edytowany)

A tu nagle niespodzianka... Pan beznadziejny programista dorobił moduł BLE do IRIS 😉 

 

Słowem wstępu

Moduł BLE jest akceptowalnie stabilny, został zaprojektowany tak, by nie zgłaszać jakichkolwiek wyjątków (poza timeout'ami, które leżą po stronie zewnętrznego programisty - jeżeli je doda to system uwzględnia ich możliwość i przekazuje wyjątek dalej).

W pozostałych przypadkach założenie całego API jest takie, by zwracać marginalną ilość wyjątków i obsługiwać każdy możliwy scenariusz - np. jeżeli chcemy podłączyć już podłączone urządzenie to zwracamy informację, że podłączenie było udane (bez wywoływania zdarzeń przy podłączeniu). W ten sposób programista wie, że urządzenie ma gwarancję połączenia, a program jest odporny na wielokrotne wywołania funkcji podłączenia.

Oraz dość ważna rzecz: działa tylko na Windowsie

 

Ogólna zasada działania

BLE w IRIS jest uproszczone - obsługuje urządzenia wykrywane za pomocą konkretnej usługi (GUID) lub konkretnej nazwy.

W przypadku GUID IRIS oczekuje na konkretne ogłoszenie od urządzenia BLE, co jest typowym podejściem do implementacji (np. jeżeli szukamy opaski mierzącej tętno to wybieramy usługę "Heart Rate Service" jako "bazę" naszego urządzenia i w momencie zgłoszenia się pierwszego urządzenia z tą usługą zostanie ono podłączone).

Nazwy są dużo bardziej skomplikowane - API monitoruje wszystkie rozgłoszenia i weryfikuje zgodność nazw przy użyciu RegEX'a. W tym przypadku gdy np. chcemy wszystkie urządzenia z prefixem DEVICE- wystarczy użyć RegEX'a (DEVICE-.*)

 

System EndPoint'ów

Sam bazowy model urządzenia posiada zaś "Endpoint'y", których nazwa została zainspirowana przez USB, ale w dużym uproszczeniu są to powiązania do konkretnych charakterystyk w konkretnych usługach urządzenia. Endpoint'y mogą być wymagane lub opcjonalne (np. opaska na ramię wymaga pomiaru pulsu, ale może mieć też opcjonalny endpoint do pomiaru SPO2 jeżeli jest dostępne).

Przykładowa rejestracja Endpoint'a w urządzeniu:

protected override async ValueTask AttachOrLoadEndpoints()
{
  // Attach the heart rate endpoint
  // we don't need to notify interface for disconnection as
  // it will be automatically handled in endpoint methods
  HeartRateEndpoint = await AttachEndpoint(HEART_RATE_ENDPOINT_ID, GattServiceUuids.HeartRate,
                       HEART_RATE_CHARACTERISTIC_INDEX, HandleHeartRateNotification);
}

Endpoint posiada własny identyfikator liczbowy (uint, powinno wystarczyć do każdego zastosowania), konkretny GUID usługi, indeks lub GUID charakterystyki.

W przypadku użycia metody LoadEndpoint(id, service, characteristic, mode = REQUIRED) nie występuje dodatkowe pole na metodę do wywołania w momencie wystąpienia notyfikacji, co ma miejsce w przypadku użycia AttachEndpoint(id, service, characteristic, callback, mode = REQUIRED) - używając AttachEndpoint automatycznie możemy zasubskrybować notyfikacje na urządzeniu.

W momencie, gdy urządzenie będzie poza zasięgiem w momencie szukania punktów krańcowych API automatycznie odłączy urządzenie jako niedostępne. W przypadku błędu protokołu spróbuje pracować dalej. Jeżeli będzie brakowało wymaganego punktu krańcowego urządzenie się rozłączy po załadowaniu wszystkich punktów.

 

Odczytywanie danych

W momencie otrzymania notyfikacji (lub chęci odczytania danych z Endpoint'a) możemy użyć metody ReadData<T> na konkretnym punkcie krańcowym:

/// <summary>
/// Process the raw data received from the device into application usable data,
/// </summary>
private async void HandleHeartRateNotification(GattCharacteristic sender, GattValueChangedEventArgs args)
{
  // If endpoint failed, return
  if (HeartRateEndpoint == null) return;

  // Read the data from the endpoint and return if it is null
  byte[]? data = await HeartRateEndpoint.ReadData<byte[]>();
  if (data == null) return;

  // Process the data
  HeartRateReadout heartRate = ProcessData(data);

  // Notify listeners
  OnHeartRateReceived(heartRate);
}

T jest ograniczone do kilkunastu podstawowych typów (liczbowe, bool, tekst, tablica bajtów, data, przedział czasowy i GUID).

W przypadku nieudanego odczytu zostanie zwrócony wskaźnik null (urządzenie może się rozłączyć jeżeli przyczyną nieudanego odczytu był brak połączenia).

Pełen kod przykładowego urządzenia można znaleźć na GitHubie.

 

Podsumowanie

Czy da się łatwo zaimplementować urządzenie BLE? Tak. Czy da się łatwo połączyć... zależy od miejsca, gdzie jest antena / dongle (polecam podłączenie na przedłużce USB, daje lepszy zasięg).

Czekają mnie jeszcze testy z pełni customowym urządzeniem (własne usługi i protokół), ale jestem dobrej myśli.

Kandydatem testowym do BLE była opaska Magene 😉 

Edytowano przez H1M4W4R1
  • Lubię! 2
Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.