Skocz do zawartości
rziomber

Obsługa DynamicDNS w serwisie FreeDNS::42 dla ESP8266 i Arduino

Pomocna odpowiedź

Masz gotowy wspaniały bulbulator oparty na chipie ESP8266 (np na modułach WiFi ESP8266 Wemos NodeMCU V3 32MB, ArduCam ESP8266-12E WiFi IoT, Adafruit Feather Huzzah ESP8266, Adafruit Huzzah ESP8266, SparkFun Thing - Dev Board - moduł WiFi ESP8266).

DSLR_intervalometers_Bluetooth_and_WiFi.thumb.jpg.74b40913299723e30ff11d51cdc25f72.jpgDew_Heater_Controller.thumb.jpg.3babab467e5fa40b761499e8c3676bdf.jpg

Tworzy on stronę WWW, którą możesz zdalnie doglądać jego pracy.

Arduino_Weather_Station_Admin_Webpage.thumb.png.2da6c4323f1b4b4423c163899710842a.pngAquarium_controller_webpage.thumb.png.719d7bf525d922fcd3d14dff37965990.pngDSLR_remote_controller_screenshot.thumb.png.be81a7299f0de636763927bd2f150e96.png

Niestety posiadasz łącze stałe ze zmiennym IP. W jaki sposób możesz więc połączyć się z nim będąc poza domem? Z pomocą przychodzą usługi typu Dynamic DNS. Jedną z nich jest polski serwis https://freedns.42.pl, z którego od lat korzystam. Zapewnia on przykładowy skrypt Pythona do uaktualniania rekordów DNS. Niestety nie skorzystamy z niego bezpośrednio w Arduino. Musimy więc napisać własny szkic. Celem podejrzenia danych wysyłanych do serwera nieco zmodyfikowałem gotowy skrypt Pythona podmieniając

server = "https://freedns.42.pl/xmlrpc.php"

na adres localhost swojego własnego programu napisanego w C++, który zapisał nagłówek i dane przekazywane do serwera. Tak oto powstał szkic Arduino zawierający trzy funkcje:

  • publicIP() - sprawdzająca aktualne publiczne IP
  • gethostbyname(String host) - sprawdzająca IP przypisane do domeny w rekordach DNS - rekord adresów (A)
  • updateDynDNS() - odpowiedzialna za uaktualnienie wpisu w serwisie FreeDNS

Możemy teraz cyklicznie wywoływać w pętli loop polecenia:

    String myIP = publicIP();
    String hostIP = gethostbyname(dnsset.subdomain + "." + dnsset.domain);

    if (myIP != hostIP)
    {
      dnsset.newaddress = myIP;
      updateDynDNS();
      Serial.println("FreeDNS IP: " + hostIP);
      Serial.println("Public IP: " + myIP);
    }

Sprawdzamy więc nasze aktualne publiczne IP, potem IP przypisane do domeny w DNS. Jeśli się nie zgadzają - wtedy uruchamiamy "machinę" odpowiedzialną za komunikację z FreeDNS. Polecam użyć jakiegoś timera czy skorzystać z funkcji millis(), nie blokującego działanie innych funkcji delay()

FreeDNS.thumb.png.41ff4d902ff72ba831b9c2454847f891.png

Cały kod źródłowy programu:

#include <ESP8266HTTPClient.h>
#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
struct FreeDNSsettings {
  String domain;
  String subdomain;
  String newaddress;
  String user;
  String password;
  String ttl;
} dnsset;

void setup() {
  dnsset.domain = "TwojaDomena.pl";
  dnsset.subdomain = "Nazwa subdomeny";
  dnsset.user = "Uzytkownik w serwisie freedns.42.pl";
  dnsset.password = "haslo uzytkownika";
  dnsset.ttl = "120";
  Serial.begin(9600);                                  //Serial connection
  WiFi.softAPdisconnect();
  WiFi.disconnect();
  WiFi.mode(WIFI_STA);
  WiFi.begin("Siec WiFi", "i haslo do niej");   //WiFi connection

  while (WiFi.status() != WL_CONNECTED) {  //Wait for the WiFI connection completion
    delay(500);
    Serial.println("Waiting for connection");
  }
}

void loop() {
  if (WiFi.status() == WL_CONNECTED) { //Check WiFi connection status
    String myIP = publicIP();
    String hostIP = gethostbyname(dnsset.subdomain + "." + dnsset.domain);

    if (myIP != hostIP)
    {
      dnsset.newaddress = myIP;
      updateDynDNS();
      Serial.println("FreeDNS IP: " + hostIP);
      Serial.println("Public IP: " + myIP);
    }
  } else {
    Serial.println("Error in WiFi connection");
  }
  delay(15 * 60 * 1000);
}

String publicIP() {
  String myIP;
  HTTPClient http;
  http.begin("http://ip.42.pl/raw"); //Specify request destination
  int httpCode = http.GET();                                                                  //Send the request

  if (httpCode > 0) { //Check the returning code
    myIP = http.getString();   //Get the request response payload
  }
  return myIP;
}

String gethostbyname(String host)
{
  IPAddress ipAddress;
  WiFi.hostByName(host.c_str(), ipAddress);
  return String(ipAddress[0]) + String(".") + \
         String(ipAddress[1]) + String(".") + \
         String(ipAddress[2]) + String(".") + \
         String(ipAddress[3]);
}

void updateDynDNS() {
  String xml = "<?xml version='1.0'?>\r\n"
               "<methodCall>\r\n"
               "<methodName>xname.updateArecord</methodName>\r\n"
               "<params>\r\n"
               "<param>\r\n"
               "<value><struct>\r\n"
               "<member>\r\n"
               "<name>name</name>\r\n"
               "<value><string>" + dnsset.subdomain + "</string></value>\r\n"
               "</member>\r\n"
               "<member>\r\n"
               "<name>zone</name>\r\n"
               "<value><string>" + dnsset.domain + "</string></value>\r\n"
               "</member>\r\n"
               "<member>\r\n"
               "<name>newaddress</name>\r\n"
               "<value><string>" + dnsset.newaddress + "</string></value>\r\n"
               "</member>\r\n"
               "<member>\r\n"
               "<name>oldaddress</name>\r\n"
               "<value><string>*</string></value>\r\n"
               "</member>\r\n"
               "<member>\r\n"
               "<name>updatereverse</name>\r\n"
               "<value><string>0</string></value>\r\n"
               "</member>\r\n"
               "<member>\r\n"
               "<name>user</name>\r\n"
               "<value><string>" + dnsset.user + "</string></value>\r\n"
               "</member>\r\n"
               "<member>\r\n"
               "<name>ttl</name>\r\n"
               "<value><string>" + dnsset.ttl + "</string></value>\r\n"
               "</member>\r\n"
               "<member>\r\n"
               "<name>password</name>\r\n"
               "<value><string>" + dnsset.password + "</string></value>\r\n"
               "</member>\r\n"
               "</struct></value>\r\n"
               "</param>\r\n"
               "</params>\r\n"
               "</methodCall>";

  String http = "POST /xmlrpc.php HTTP/1.1\r\n"
                "Host: freedns.42.pl\r\n"
                "Accept-Encoding: gzip\r\n"
                "Content-Type: text/xml\r\n"
                "User-Agent: Python-xmlrpc/3.5\r\n"
                "Content-Length: " + String(xml.length()) + "\r\n"
                "\r\n";

  xml = http + xml;

  WiFiClientSecure client;
  IPAddress ipAddress;
  WiFi.hostByName("freedns.42.pl", ipAddress);
  client.connect(ipAddress, 443);
  client.print(xml);
}

Biblioteka WiFiClientSecure występuje w środowisku ESP8266 relatywnie od niedawna. Jeśli macie problemy z kompilacją szkicu właśnie z jej powodu - uaktualnijcie obsługę ESP w Arduino IDE.

Po niewielkich modyfikacjach przypuszczalnie (niestety chwilowo nie mogę tego sprawdzić) uaktualniacz DNS działać będzie również z mikrokontrolerem ESP32. Chyba wystarczy podmienić nazwy dołączanych bibliotek na:

#include <HTTPClient.h>
#include <WiFi.h>
#include <WiFiClientSecure.h>

 

Edytowano przez rziomber

Udostępnij ten post


Link to post
Share on other sites

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.

@rziomber, witam na forum 😉 Widzę, że to Twoje pierwsze kroki na Forbocie, oto najważniejsze informacje na start:

  • Chcesz przywitać się z innymi członkami naszej społeczności? Skorzystaj z tematu powitania użytkowników.
  • Opis najciekawszych funkcji, które ułatwiają korzystanie z forum znajdziesz w temacie instrukcja korzystania z forum - co warto wiedzieć?
  • Poszczególne posty możesz oceniać (pozytywnie i negatywnie) za pomocą reakcji - ikona serca w prawym dolnym rogu każdej wiadomości.

Właśnie zaakceptowałem Twój opis, możesz go teraz zgłosić do akcji rabatowej umieszczając link w temacie zbiorczym. Dziękuję za przedstawienie ciekawego projektu, zachęcam do prezentowania kolejnych DIY oraz aktywności na naszym forum 🙂

Udostępnij ten post


Link to post
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Gość
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.


×
×
  • Utwórz nowe...