Skocz do zawartości

Klient MQTT dla ATXMega128A3U i W5100


Pomocna odpowiedź

Napisano

Ładnych parę lat temu złożyłem płytkę, w której wykorzystałem mikrokontroler ATXMega128A3U oraz układ Wiznet W5100 (kontroler Ethernet ze sprzętową obsługą stosu TCP/IP). Po jakimś czasie płytka wylądowała na półce, jednak teraz chciałbym ją wykorzystać w pewnym projekcie. Zupełnie zdaję sobie sprawę z tego, że hardware się zestarzał, jednak do przewidzianych zastosowań powinien w zupełności wystarczyć.

W momencie odłożenia na półkę zaledwie wstępnie przetestowałem hardware i na szybko sprawdziłem działanie W5100 za pomocą kawałka kodu znalezionego w sieci. Nie uruchamiałem bardziej złożonych protokołów. Teraz jednak okazało się, że producent wrzucił do sieci cała bibliotekę sterowników do układów z tej rodziny. Udało mi się wstępnie przeportować przykłady dla Raspberry Pi Pico, z tego reporytorium. Pełnym sukcesem tego nie mogę nazwać, ale udało się zrobić krok do przodu - W5100 łączy się z siecią lokalną i jest w stanie nawiązywać połączenia. Udało mi się uruchomić klienta DHCP i SNTP. Nie obyło się bez problemów wynikających z innej architektury, bo np. w kodzie SNTP była cała seria przesunięć bitowych w lewo bez "UL" przy wartości, przez co GCC dla AVR wybierał domyślnie wartość 16bit, która zawijała się przy większych przesunięciach. W RpiPico nie było tego problemu, bo ARM w ten sytuacji zastosuje zmienną 32bit.

Niestety, większym problemem okazał się klient MQTT (w przypadku mojego projektu jedna z podstawowych funkcjonalności). Repozytorium od producenta poza sterownikami samego scalaka zawiera także kod do obsługi paru popularnych protokołów. Wygląda na to, że w przypadku MQTT użyto popularnej implementacji Paho MQTT z dodanym interfejsem do komunikacji z siecią poprzez W5100 (albo inne układy z tej rodziny).

Niestety klient MQTT nie do końca zachowuje się tak, jak powinien. O ile jestem w stanie połączyć się z brokerem i wysyłać wiadomości, to odbieranie wiadomości z zasubskrybowanych tematów albo nie działało wcale, albo działało niestabilnie (callback był wołany raz na jakiś czas). Do tego zauważyłem, że funkcja wołana w pętli głównej funkcja MQTTYield() cały czas zwraca -1.

Udało mi się znaleźć przyczynę - wygląda na to, że sam kod z repozytorium zawiera błąd. Tutaj mamy funkcję odpowiedzialną za odczyt danych z socketu przez Paho:

 

int w5x00_read(Network* n, unsigned char* buffer, int len, long time) {

    if ((getSn_SR(n->my_socket) == SOCK_ESTABLISHED) && (getSn_RX_RSR(n->my_socket) > 0)) {
        return recv(n->my_socket, buffer, len);
    }
    
    return SOCK_ERROR;
}

Problem polega na tym, że PahoMqtt oczekuje blokującego odczytu - funkcja ma czekać na pojawienie się danych i zwrócić kontrolę dopiero po upłynięciu timeoutu. Jak widać tutaj timeout jest zupełnie ignorowany, a funkcja zwróci błąd natychmiast po zauważeniu, że w buforze socekutu nie ma danych. Błąd ten będzie propagowany w górę, aż do MQTTYield.

Tymczasowo przygotowałem testową wersję funkcji, która obsługuje timeout:

int w5x00_read(Network* n, unsigned char* buffer, int len, long time) {
    uint32_t start = millis();
    
    if (getSn_SR(n->my_socket) != SOCK_ESTABLISHED) {
        return SOCK_ERROR;
    }
    
    while (getSn_RX_RSR(n->my_socket) == 0) {
        if ((uint32_t)(millis() - start) >= time) {
            return SOCK_ERROR;
        }
    }
    
    return recv(n->my_socket, buffer, len);
}

Jest lepiej, ale wciąż nie jest idealnie. Przede wszystkim funkcja blokuje pętlę główną, wstrzymując wykonywanie innych operacji (co w skrajnym przypadku spowoduje reset przez WDT). Co gorsze nawet teraz kod nie działa poprawnie i ciągle nie jestem w stanie odbierać wiadomości z zasubskrybowanych tematów.

Może ktoś mógłby polecić jakąś alternatywą? Istnieje jakiś sprawdzony klient MQTT, który byłby w stanie działać na małych mikrokontrolerach, bez RTOS-a i był zdolny do pracy w trybie nieblokujących odczytów?

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...