-
11. Data: 2022-08-09 19:13:46
Temat: Re: Biblioteka MQTT i dziwny kod w C
Od: "J.F" <j...@p...onet.pl>
On Tue, 9 Aug 2022 07:13:17 +0200, JDX wrote:
> On 08.08.2022 19:14, Atlantis wrote:
> [...]
>> BYTE llen;
>> WORD len= MQTTReadPacket(&llen);
>>
> Ewidentny błąd - pokazuje dlaczego należy kompilować z -Wall (oraz
> ewentualnie -pedantic) i nie ignorować ostrzeżeń. Aczkolwiek w
> przytoczonym kontekście nie ma znaczenia - zmienna llen ma zasięg
> lokalny ograniczony do wnętrza if-a i poza wywołaniem MQTTReadPacket()
> nigdzie nie jest tam później używana.
Blad troche dziwaczny, bo w ogole nie widze definicji MQTTReadPacket
z parametrem. Jak to zwykłe C, i parametr nie ma znaczenia,
to nadal dziwaczne.
Podejrzewam, ze cos tu przerabiali, i zrezygnowali z podawania adresu.
Ale nawet tam, gdzie tak piszą, to nie widzę aby uzywali tego llen,
czyli błąd w zasadzie bez znaczenia.
Dane będą w MQTTBuffer ?
A jak Atlantis zauwazyl - program bierze z rxBF, tylko juz tam nic nie
zapisuje.
Wyglada na to, jakby kod byl w połowie wiekszych przeróbek.
>> Potem zawartość takiej zmiennej jest wykorzystywana w kodzie jako
>> element indeksu tablicy MQTTBuffer - również w tych częściach kodu,
>> które działały prawidłowo. Szybkie poszukiwania w internecie ujawniły,
>> że możliwość zdeklarowania pustej listy argumentów to historyczna
>> zaszłość. Wszyscy przestrzegają przed robieniem tego. Natomiast nigdzie
>> nie mogę znaleźć informacji o tym, w jaki sposób to działa i co
>> właściwie robią te kawałki kodu. Ktoś ma jakiś pomysł?
> Nie jestem pewny co oznaczają ,,te kawałki kodu", ale w ramach testu
> proponuję odnaleźć ten kontekst:
>
> if(MQTTAvailable()) {
> BYTE llen;
> WORD len = MQTTReadPacket(&llen);
> WORD msgId = 0;
> BYTE *payload;
>
> i zaraz po deklaracjach zmiennych dopisać llen = len.
ale o co im by mialo chodzic? Czemu mieliby uzywac llen - len
niedobre?
> No i proponuję też zamienić
> switch(rxBF[1]) { //MQTTBuffer
> na
> switch(MQTTBuffer[1]) { //MQTTBuffer
J.
-
12. Data: 2022-08-09 20:38:31
Temat: Re: Biblioteka MQTT i dziwny kod w C
Od: Atlantis <m...@w...pl>
On 09.08.2022 19:13, J.F wrote:
> Blad troche dziwaczny, bo w ogole nie widze definicji MQTTReadPacket
> z parametrem. Jak to zwykłe C, i parametr nie ma znaczenia,
> to nadal dziwaczne.
To jest właśnie jakaś zaszłość historyczna, o której sam wcześniej nie
miałem pojęcia. W C++ funkcja z pustą listą parametrów równa się funkcji
z parametrem void. Jednak w C działa to inaczej - pusta lista parametrów
oznacza niesprecyzowaną liczbę parametrów. Do takiej funkcji możemy
przekazać albo nic, albo cokolwiek i taki kod się skompiluje, jednak z
wnętrza funkcji do tych parametrów i tak nie będziemy mieć dostępu.
Liczyłem na to, że może jakaś ezoteryka języka pozwala na niejawne
przekazanie czegoś w ten sposób jednak wychodzi na to, że ktoś po prostu
zmieniał tę funkcję i po prostu usunął parametry zamiast przerobić
funkcję na void.
> Ale nawet tam, gdzie tak piszą, to nie widzę aby uzywali tego llen,
> czyli błąd w zasadzie bez znaczenia.
> Dane będą w MQTTBuffer ?
Dane powinny trafić do MQTTBuffer, jednak z tego co widzę funkcja
MQTTReadPacket() w jej obecnej formie nie radzi sobie z wiadomością
CONNACK. Odczytuje tylko dwa pierwsze bajty (nagłówek) ale już nie dwa
kolejne, z czego nas interesuje ostatni - result code.
> Wyglada na to, jakby kod byl w połowie wiekszych przeróbek.
Na to wygląda. Udało mi się skontaktować z autorem wcześniejszej wersji
tej biblioteki na PIC32. To znaczy wcześniejszej w stosunku do tego, co
sam znalazłem na GitHubie. A i on prawdopodobnie opierał się na jakimś
wcześniejszym kodzie. Przesłał mi jakąś swoją starą wersję kodu -
nietestowaną i jak się okazało niedziałającą przez kilka bugów (m.in.
powodujących zatrzaskiwanie się maszyny stanów albo błędy podczas
czytania z socketa). Co jednak istotne, w tej wersji kodu funkcja
MQTTReadPacket przyjmowała jeden parametr - wskaźnik na BYTE. Wychodzi
się na to, że pusta lista parametrów powstała, gdy ktoś później
przepisywał ten kod.
Wychodzi na to, że trzeba będzie teraz przyjrzeć się tej funkcji i
ustalić, czemu nie parsuje prawidłowo CONNACT.
> ale o co im by mialo chodzic? Czemu mieliby uzywac llen - len
> niedobre?
Rozróżnienie na len i llen bierze się ze specyfiki MQTT. W podstawowych
wiadomościach (np. kontrolnych) mamy niewielką wartość len. Jednak gdy
trzeba np. załączyć większy payload, załącza się jeszcze dodatkową
informację. Podejrzewam, że w takich sytuacjach obydwie wartości mogą
być potrzebne do manipulowania do manipulowania buforem. Z drugiej
strony obecna wersja MQTTReadPacket posiada lokalną, statyczną tablice o
nazwie lengthLength, która może być właśnie do tego wykorzystywana.
-
13. Data: 2022-08-10 00:06:33
Temat: Re: Biblioteka MQTT i dziwny kod w C
Od: Atlantis <m...@w...pl>
Sprawa ciągle nie daje mi spokoju, wiec przyjrzałem się jeszcze raz
trochę bliżej działaniu funkcji MQTTReadPacket(). Nadal nie wiem jak
rozwiązać problem, ale sprawa przynajmniej się trochę wyjaśniła.
W uproszczeniu korzystanie z tej funkcji wygląda następująco:
case MQTT_CONNECT_ACK
WORD len = MQTTReadPacket();
if (len >= 2) {
//Tutaj wykonują się główne operacje
//Tylko tutaj może zostać zmieniony stan maszyny stanów
}
break;
Funkcja może być wywołana w tym miejscu wielokrotnie i dalej przejdziemy
dopiero wtedy, gdy zwróci ona dwa lub więcej (wartość ta oznacza liczbę
bajtów zapisanych do bufora). Sama funkcja MQTTReadPacket również
posiada swoją własną maszynę stanów, której wartość jest zapisywana w
lokalnej zmiennej statycznej. Od stanu tej maszyny zależy co funkcja zwróci.
Dopisałem do kodu kilka printf-ów, żeby zobaczyć co się tam dzieje.
Wynik wygląda następująco:
Tutaj wywolujemy MQTTReadPacket() w MQTT_CONNECT_ACK
m_state=0 <- stan po wywołaniu funkcji w MQTT_CONNECT_ACK
len=2 <- wartość zwrócona
Tutaj wywołania w innych częściach programu
m_state=2
m_state=3
m_state=0
Tutaj wywolujemy MQTTReadPacket() w MQTT_CONNECT_ACK
m_state=2 <- stan po wywołaniu funkcji w MQTT_CONNECT_ACK
len=0 <- wartość zwrócona
Tutaj wywolujemy MQTTReadPacket() w MQTT_CONNECT_ACK
m_state=3 <- stan po wywołaniu funkcji w MQTT_CONNECT_ACK
len=0 <- wartość zwrócona
Tutaj wywolujemy MQTTReadPacket() w MQTT_CONNECT_ACK
m_state=0 <- stan po wywołaniu funkcji w MQTT_CONNECT_ACK
len=2 <- wartość zwrócona
Tutaj wywołania w innych częściach programu
m_state=2
m_state=3
m_state=0
Jak widać maszyna stanów przy kolejnych wywołaniach funkcji
MQTTReadPacket() posiada wartości 0, 2 albo 3.
Jeśli funkcja zostanie wywołana gdy jej maszyna będzie w stanie 0, to
zwrócona zostanie wartość 2 - spowoduje to, że będziemy mogli wejść do
ifa i wykonać operacje przewidziane dla MQTT_CONNECT_ACK.
Jeśli jednak w momencie wywołania funkcji jej maszyna stanów będzie
ustawiona na 2 albo 3, zwrócone zostanie zero. If się nie wywoła, a wiec
nie opuścimy MQTT_CONNECT_ACK i wrócimy do tego samego miejsca w
kolejnym obiegu pętli.
Co więcej - wywołania MQTTReadPacket w innych miejscach programu również
biorą udział w tym cyklu.
Kolejny wniosek jest taki, że "magiczne liczby" w switch/case wewnątrz
MQTTReadPacket to tak naprawdę kolejne etapy pracy maszyny stanów tej
funkcji.
Więc główny problem polega teraz na tym, żeby w tym miejscu nie było
zwracane 2, ale 4. Do MQTTBuffer powinny trafiać cztery bajty, a
ostatnio z nich będzie kodem wyniku, przesyłanym w pakiecie CONNACK.
Konieczna będzie dokładniejsza analiza tego, co właściwie ta funkcja
robi. :)
-
14. Data: 2022-08-10 00:13:41
Temat: Re: Biblioteka MQTT i dziwny kod w C
Od: JDX <j...@o...pl>
On 09.08.2022 19:13, J.F wrote:
[...]
> Blad troche dziwaczny, bo w ogole nie widze definicji MQTTReadPacket
> z parametrem. Jak to zwykłe C, i parametr nie ma znaczenia,
> to nadal dziwaczne.
Błąd człowieka, na który pozwala język C, w szczególności stare
standardy. Od C11 (aka ISO/IEC 9899:2011) takie deklaracje zostały
uznane za przestarzałe (chociaż nadal dopuszczalne).
Tu masz to opisane razem z cytatami ze standardu/ów:
https://stackoverflow.com/questions/13950642/why-doe
s-a-function-with-no-parameters-compared-to-the-actu
al-function-definiti
https://stackoverflow.com/questions/18378993/c-and-d
efining-a-function-prototype-with-no-parameters
-
15. Data: 2022-08-10 09:52:16
Temat: Re: Biblioteka MQTT i dziwny kod w C
Od: "J.F" <j...@p...onet.pl>
On Wed, 10 Aug 2022 00:13:41 +0200, JDX wrote:
> On 09.08.2022 19:13, J.F wrote:
> [...]
>> Blad troche dziwaczny, bo w ogole nie widze definicji MQTTReadPacket
>> z parametrem. Jak to zwykłe C, i parametr nie ma znaczenia,
>> to nadal dziwaczne.
> Błąd człowieka, na który pozwala język C, w szczególności stare
> standardy. Od C11 (aka ISO/IEC 9899:2011) takie deklaracje zostały
> uznane za przestarzałe (chociaż nadal dopuszczalne).
>
> Tu masz to opisane razem z cytatami ze standardu/ów:
>
> https://stackoverflow.com/questions/13950642/why-doe
s-a-function-with-no-parameters-compared-to-the-actu
al-function-definiti
>
> https://stackoverflow.com/questions/18378993/c-and-d
efining-a-function-prototype-with-no-parameters
Jest to moze i jakis błąd, ale jest szerszy - C pozwala na wywołanie
funkcji z dowolną listą parametrow, bo inaczej printf nie moglby
dzialac.
Co prawda powinno to zostac zdefinioniowane z uzyciem "..."
... no to moze i jest jakis błąd kompilatora, ze nie zgłasza rożnic
w prototypie, deklaracji i wywolaniach ...
J.
-
16. Data: 2022-08-10 09:59:20
Temat: Re: Biblioteka MQTT i dziwny kod w C
Od: "Grzegorz Niemirowski" <g...@g...net>
J.F <j...@p...onet.pl> napisał(a):
> Jest to moze i jakis błąd, ale jest szerszy - C pozwala na wywołanie
> funkcji z dowolną listą parametrow, bo inaczej printf nie moglby
> dzialac.
Ale właśnie...
> Co prawda powinno to zostac zdefinioniowane z uzyciem "..."
> ... no to moze i jest jakis błąd kompilatora, ze nie zgłasza rożnic
> w prototypie, deklaracji i wywolaniach ...
> J.
...printf z tego nie korzysta. On ma taką deklarację:
int printf ( const char * format, ... );
Czyli przyjmuje jeden lub więcej parametrów i jest to po ludzku określone.
Do niczego nie jest mu potrzebny ten dziwny mechanizm z pustą listą
argumentów.
--
Grzegorz Niemirowski
https://www.grzegorz.net/
-
17. Data: 2022-08-10 19:25:51
Temat: Re: Biblioteka MQTT i dziwny kod w C
Od: Atlantis <m...@w...pl>
Ok, posiedziałem nad tym jeszcze przez kilka godzin i udało mi się
znaleźć przyczynę. W wielkim skrócie maszyna stanów w funkcji
MQTTReadPacket była źle napisana. Jeden if nie wykonywał się wcale, a
część kodu w dalszej części była pomijana zupełnie z uwagi "break"
umieszczony w złym miejscu. Efekt był taki, że kod przechodził dalej już
po odebraniu nagłówka pakietu i nie pobierał pozostałych dwóch bajtów.
Biblioteka w takiej formie działała tylko dlatego, że w wyniku innego
błędu kod zawsze zakładał, że autoryzacja przeszła poprawnie. ;)
Z uwagi na wadliwość tej funkcji rzecz jasna nie miały szans działać
jakiekolwiek inne funkcje związane z odbieraniem danych od brokera.
Niewykluczone zresztą, że będę musiał przeprowadzić dodatkowe testy i
poprawić jeszcze kilka błędów, zanim uda mi się uruchomić sprawdzanie
wiadomości PUBLISHACK albo subskrybowanie tematu i odbieranie wiadomości
przychodzących od brokera.
Wireskark pokazuje także, że mam trochę retransmisji TCP na porcie MQTT,
więc temu też jeszcze będę musiał się przyjrzeć.
Na chwilę obecną działa jednak najważniejsze - wrzucanie danych na
serwer. Jeśli ktoś byłby zainteresowany, to po posprzątaniu mogę się tym
podzielić. O ile ktoś jeszcze używa PIC32 z bibliotekami MLA i będzie
potrzebował obsługi MQTT. :)
-
18. Data: 2022-08-10 20:41:36
Temat: Re: Biblioteka MQTT i dziwny kod w C
Od: heby <h...@p...onet.pl>
On 10/08/2022 19:25, Atlantis wrote:
> podzielić. O ile ktoś jeszcze używa PIC32 z bibliotekami MLA i będzie
> potrzebował obsługi MQTT. :)
Teraz, to się używa ESP8266/ESP32 do tego a nie jakieś PICe od migania
ledami ;)
-
19. Data: 2022-08-10 22:06:33
Temat: Re: Biblioteka MQTT i dziwny kod w C
Od: Marek <f...@f...com>
On Wed, 10 Aug 2022 20:41:36 +0200, heby <h...@p...onet.pl> wrote:
> Teraz, to się używa ESP8266/ESP32 do tego a nie jakieś PICe od
> migania
> ledami ;)
Uu pic32 od migania ledami, mocne.
--
Marek
-
20. Data: 2022-08-10 22:43:23
Temat: Re: Biblioteka MQTT i dziwny kod w C
Od: "Grzegorz Niemirowski" <g...@g...net>
Atlantis <m...@w...pl> napisał(a):
> Jeśli ktoś byłby zainteresowany, to po posprzątaniu mogę się tym
> podzielić.
Ja nie potrzebuję, ale może po prostu wrzuć na githuba, to ktoś spoza pme
też skorzysta i nie będzie się musiał męczyć z tamtym kodem.
--
Grzegorz Niemirowski
https://www.grzegorz.net/