Skocz do zawartości

Żonglowanie danymi ESP8266 poprzez HTTP klient - serwer.


Pomocna odpowiedź

Napisano

Witam!

Mam napisany własnoręcznie przykładowy kod serwera. Serwer stawia AP, na którym co sekundę zmienia sobie wartość zmiennej typu bool, a pod adresem dataserver.local wyrzuca ją w formie JSON: kod źródłowy serwera. Drugi ESP został oprogramowany jako klient - łączy się pod postawione AP. Ma on również odpytywać serwer poprzez wcześniej wspomniany adres i pobierać JSON (na razie) do zmiennej tekstowej: kod źródłowy klienta.

Kod napisany jest w miarę porządnie (pomijając delay w kliencie). Niestety nie mam pojęcia czemu klient zwraca ciągle: Error: connection refused. Trochę debugowałem kod i pomimo całej prawidłowości połączenia HTTP to zmienna httpCode ma wartość -1 jakby serwer nie odpowiadał klientowi. Adresy IP są z tej samej puli, bramy się zgadzają. O dziwo po podpięciu się telefonem pod AP serwera i wejściu na ustawiony adres serwer bez problemu odpowiada.

Może ktoś ma jakiś pomysł co może być nie halo?

Z góry dzięki!

Problem częściowo rozwiązany. Okazało się, że klient po podpięciu pod serwer nie umiał rozszyfrować adresu mDNS "dataserver.local". Po milionach prób i ustawieniu zmiennej klienta z adresem na:

const char *url = "http://192.168.4.1/";

wreszcie zabanglało i pozwoliło przesyłać dane! Niestety średnio satysfakcjonuje mnie takie rozwiązanie, ponieważ jest mało przenośne. Serwer po to wystawiał mDNS aby klient mógł bez konkretnej znajomości adresu odczytać dane z serwera. Czy ma ktoś może z tutaj obecnych (jeżeli do jasnej cholery ktokolwiek mnie czyta bo to już 4 mój pusty temat) propozycję na wyciągnięcie adresu serwera aby móc go odpytać o dane? Może DHCP i brama domyślna? Tylko jak wtedy skleić z obiektu IPAddress taki ładny URL jak u góry? Bo klient HTTP jest dość wrażliwy na znaczki.

A czemu mDNS a nie DNS? Do dwie zupełnie różne sprawy i resolver wcale nie musi się na obu znać. Masz przecież bibliotekę DNS na ESP, prawda (jeśli - jak raczyłeś się sam wyrazić - do jasnej cholery czytujesz czasami dokumentację zanim zaczniesz na forach d... zawracać) ?

A taki ładny adres... nie wiem czy zauważyłeś, ale IPAddress ma takie fajne metody jak fromString i toString, o nie chodzi?

  • Pomogłeś! 1

Wielkie dzięki za podrzucenie pomysłu z samym DNS. Było dość proste w implementacji, a dodatkowo serwer DNS może odpowiadać na wszystkie domeny dzięki drugiemu parametrowi ustawionemu na "*". Niestety klient wciąż nie wiem czemu nie potrawi rozwiązać serwowanej nazwy domeny. Próbowałem na miliony sposobów: domeny z końcówką .local .pl .com .org, z końcowym slashem i bez, z początkiem http i bez. Wciąż connection refused

Kod klienta: https://pastebin.com/F3Kmd16D

Kod serwera: https://pastebin.com/RvdWh4Ce

W kodzie klienta mam tam zakomentowany sposób na generowanie url z gateway'a. On działa, ale chciałem opanować od razu połączenie po nazwie domenowej. Oczywiście, żeby było wciąż zabawnie, po podłączeniu się telefonem pod sieć serwera z ustawioną "*", każdy adres jest poprawnie rozwiązywany i kierowany na stronę z danymi.

Na pierwszy rzut oka wszystko wygląda bardo ślicznie...

Ja bym sprawdził:

1) czy faktycznie klient wie jaki jest IP serwera DNS - WiFi.dnsIP();

2) jeśli wie, czy potrafi rozwiązać nazwę (dns_gethostbyname());

Niestety - mam tylko jedną wolną płytkę ESP, więc nie mam jak sprawdzić 😞

 

Sprawdziłem zgodnie z zaleceniem:

1) WiFi.dnsIP() zwraca poprawny adres serwera DNS: 192.168.4.1

2) Nie mam bladego pojęcia jak wywołać podaną powyżej metodę. Może dlatego, że posiadam dokładnie płytkę NodeMCU, a nie czyste ESP8266. Podobno istnieje jakaś klasa DNSClient, która posiada metodę "getHostByName" ale nawet jej nie umiem w żaden sposób namierzyć aby ją wgrać do IDE i wrzucić w projekt.

Wywołać po prostu - to nie jest metoda a funkcja.

NodeMCU to nic innego jak czyste ESP8266 nalutowane na jakiś kawałek laminatu ze ścieżkami i paroma innymi  drobiazgami.

Fragment mojego kodu:

    
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

extern "C" {
#include "user_interface.h"
#include "lwip/err.h"
#include "lwip/dns.h"
}

// dalej w jakiejśtam funkcji, zwracającej czy adres został rozwiązany

int getHostByNameA(const char *hostname)
{
    static ip_addr_t ipaddr;
    if (dns_status == 1 && millis() - last_dns_query < 10000UL) { // to takie prywatne...
        return 1;
    }
    dns_status = 0;
    resolvedHost = static_cast<uint32_t>(0);
    last_dns_query = millis();
    if (resolvedHost.fromString(hostname)) {
        dns_status = 2;
        return 0;
    }
    err_t err = dns_gethostbyname(hostname, &ipaddr, &dnsFoundCallback, NULL);
    if(err == ERR_OK) {
        resolvedHost = ipaddr.addr;
        dns_status = 2;
        return 0;
    }
    if (err == ERR_INPROGRESS) {
        dns_status = 1;
        return 0;
    }
    dns_status = 2;
    return 0;
}

 

Wrzuciłem taki kodzik:

ip_addr_t ipaddr;
err_t err = dns_gethostbyname("dataserver.local", &ipaddr, NULL, NULL);
Serial.print("ERR_T: ");
Serial.println(err);
Serial.print("ip_addr_t: ");
Serial.println(ipaddr.addr);

W konsoli wypluło to:

ERR_T: -5
ip_addr_t: 4277137406

Niestety nie rozumiem nic z tego bo samo dns_gethostbyname jest tak niskopoziomowe że biegam po omacku nawet z dokumentacją.

To teraz sobie przelicz na cztery bajty.

Niestety - jeśli chcesz cokolwiek robić z IPv4 musisz wiedzieć jak wygląda adres w różnych postaciach. W tym przypadku po konwersji na hex masz 0xfeefeffe - czyli na pewno nie to czego oczekiwałeś.

Ale - zaglądając sobie do definicji widzimy:

#define ESPCONN_INPROGRESS -5 /* Operation in progress    */

Czyli przekładając na ludzki język - klient wysłał żądanie do serwera, a serwer jeszcze nie odpowiedział.

Poczekaj sobie aż err zmieni się z ERR_INPROGRESS na jakąś inną wartość, dopiero wtedy możesz liczyć na jakąś sensowną wartość w ipaddr - lub na informację, że rozwiązanie adresu się nie powiodło.

 

Niestety nic z tego. Przerzuciłem wszystko do pętli loop() deklarując zmienne wczesniej i czekałem na odpowiedź. Adres zwracany to "0" a kod to wciąż -5. Czyżby serwer był źle ustawiony?

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