diff --git a/.github/workflows/arduino-lint-actions.yaml b/.github/workflows/arduino-lint-actions.yaml new file mode 100644 index 0000000..1c18b7b --- /dev/null +++ b/.github/workflows/arduino-lint-actions.yaml @@ -0,0 +1,7 @@ +on: [push, pull_request] +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: arduino/arduino-lint-action@v1 diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..0526c6c --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 3.5) +idf_component_register(SRCS EspDDNS.cpp Esp32Util.cpp + INCLUDE_DIRS "./" + REQUIRES "arduino" # Library requires Arduino + ) +project(EspDDNS) diff --git a/Esp32Util.cpp b/Esp32Util.cpp new file mode 100644 index 0000000..4b6ac34 --- /dev/null +++ b/Esp32Util.cpp @@ -0,0 +1,99 @@ + +/* +MIT License + +Copyright (c) 2023 Amitesh Singh + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#if defined(ESP32) +#include +#include "Esp32Util.h" +#include + +esp_netif_t* get_esp_interface_netif(esp_interface_t interface); + +namespace ddns +{ + IPv6Address esp32experimental::globalIPv6() + { + esp_ip6_addr_t addr; + + if(esp_netif_get_ip6_global(get_esp_interface_netif(ESP_IF_WIFI_STA), &addr)) + { + return IPv6Address(); + } + + return IPv6Address(addr.addr); + } + + void esp32experimental::wifi_dns6_found_callback(const char *name, const ip_addr_t *ipaddr, void *data) + { + dns_api_msg *msg = static_cast(data); + + if(ipaddr && !msg->result) + { + msg->ip_addr = *ipaddr; + msg->result = 1; + } + else + { + msg->result = -1; + } + } + + bool esp32experimental::hostByName6(const char* hostname, ip_addr_t& result) + { + ip_addr_t addr; + dns_api_msg arg = {}; + bool ip_found = true; + + //err_t err = dns_gethostbyname(aHostname, &addr, wifi_dns6_found_callback, &arg); + err_t err = dns_gethostbyname_addrtype(hostname, &addr, wifi_dns6_found_callback, &arg, + LWIP_DNS_ADDRTYPE_IPV6); + + if(err == ERR_OK) + { + result = addr; + } + else if(err == ERR_INPROGRESS) + { + uint8_t retries = 0; //for 5s + while (arg.result == 0) + { + //wait here. + delay(100); + if (retries++ > 50) + { + ip_found = false; + break; + } + } + + if (ip_found) + { + result = arg.ip_addr; + } + } + + return err == ERR_OK or (err == ERR_INPROGRESS and arg.result == 1 and ip_found == true); + } +} +#endif diff --git a/Esp32Util.h b/Esp32Util.h new file mode 100644 index 0000000..8fc78aa --- /dev/null +++ b/Esp32Util.h @@ -0,0 +1,53 @@ +/* +MIT License + +Copyright (c) 2023 Amitesh Singh + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#pragma once + +#if defined(ESP32) +#include "IPv6Address.h" + +extern "C"{ +#include "lwip/opt.h" +#include "lwip/tcp.h" +#include "lwip/inet.h" +#include "lwip/dns.h" +} + +namespace ddns +{ + class esp32experimental + { + struct dns_api_msg + { + ip_addr_t ip_addr; + int result; + }; + + static void wifi_dns6_found_callback(const char *name, const ip_addr_t *ipaddr, void *callback_arg); + public: + static bool hostByName6(const char* hostname, ip_addr_t& result); + static IPv6Address globalIPv6(); + }; +} +#endif diff --git a/EspDDNS.cpp b/EspDDNS.cpp new file mode 100644 index 0000000..eb9c0f2 --- /dev/null +++ b/EspDDNS.cpp @@ -0,0 +1,242 @@ +/* +MIT License + +Copyright (c) 2023 Amitesh Singh + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#include "EspDDNS.h" + +#if defined(ESP32) +#include "IPv6Address.h" +#include "Esp32Util.h" +extern "C"{ +#include "lwip/opt.h" +#include "lwip/tcp.h" +#include "lwip/inet.h" +#include "lwip/dns.h" +} +#endif + + +namespace ddns +{ + IPAddress updater::getPublicIPv4() + { + WiFiClient client; + HTTPClient http; + http.begin(client, public_ip_finder_url); + int httpCode = http.GET(); + IPAddress public_ip; + + if (httpCode == HTTP_CODE_OK) + { + public_ip.fromString(http.getString()); + } + + http.end(); + + return public_ip; + } + + void updater::getEspIPv6() + { + #if defined(ESP8266) + #if LWIP_IPV6 + for (auto addr : addrList) + { + if (!addr.isLocal() && addr.isV6()) + { + esp_ipv6_.fromString(addr.toString()); + break; + } + } + #endif + #endif + + #if defined(ESP32) + esp_ipv6_ = esp32experimental::globalIPv6(); + #endif + } + + void updater::getEspIPv4(bool use_local_ip) + { + if (use_local_ip) + { + esp_ipv4_ = WiFi.localIP(); + } + else + { + //get the public IP + esp_ipv4_ = getPublicIPv4(); + } + } + + void updater::getDDNSIPv4(const String &domain) + { + int ret = WiFi.hostByName(domain.c_str(), duckdns_ipv4_); + if (ret != 1) + { + dns_success_ = false; + return; + } + + dns_success_ = true; + } + + void updater::getDDNSIPv6(const String &domain) + { +#if defined(ESP8266) + #if LWIP_IPV6 + ip_addr_t ip6_dns; + IP_ADDR6(&ip6_dns,PP_HTONL(0x20014860UL), PP_HTONL(0x48600000UL), PP_HTONL(0x00000000UL), PP_HTONL(0x00008888UL)); + + dns_setserver(0, &ip6_dns); + + int ret = WiFi.hostByName(domain.c_str(), duckdns_ipv6_); + if (ret != 1) + { + dns_success_ = false; + return; + } + dns_success_ = true; + #endif +#endif +#if defined(ESP32) + ip_addr_t ipv6_addr; + bool ret = esp32experimental::hostByName6(domain.c_str(), ipv6_addr); + if (!ret) + { + dns_success_ = false; + return; + } + + dns_success_ = true; + duckdns_ipv6_ = IPv6Address(ipv6_addr.u_addr.ip6.addr); +#endif + } + + bool updater::connect(const String &url) + { + WiFiClient client; + HTTPClient http; + + http.begin(client, url); + int http_code = http.GET(); + bool ret = http_code != HTTP_CODE_OK ? false : true; + + http.end(); + + return ret; + } + + bool duckdns::update(const String &domain, const String &token, ip_type ipt, bool use_local_ip) + { + String url; + + if (ipt == ip_type::IPv6) + { +#if defined(ESP8266) + #if LWIP_IPV6 + getEspIPv6(); + getDDNSIPv6(domain); + if (dns_success_ and esp_ipv6_ == duckdns_ipv6_) return false; + + url = "http://www.duckdns.org/update?domains=" + domain + "&token=" + token + "&ipv6=" + esp_ipv6_.toString(); + #else + return false; + #endif +#endif + +#if defined(ESP32) + getEspIPv6(); + getDDNSIPv6(domain); + if (dns_success_ and esp_ipv6_ == duckdns_ipv6_) return false; + + url = "http://www.duckdns.org/update?domains=" + domain + "&token=" + token + "&ipv6=" + esp_ipv6_.toString(); +#endif + } + else if (ipt == ip_type::IPv4) + { + getEspIPv4(use_local_ip); + getDDNSIPv4(domain); + if (dns_success_ and esp_ipv4_ == duckdns_ipv4_) return false; + + url = "http://www.duckdns.org/update?domains=" + domain + "&token=" + token + "&ip=" + esp_ipv4_.toString(); + } + + bool ret = connect(url); + + return ret; + } + + bool client::update(bool use_local_ip) + { + bool ret { false }; + + if (ip_type_ == ip_type::IPv4 + || ip_type_ == ip_type::IPv6) + { + ret = updater_->update(domain_, token_, ip_type_, use_local_ip); + if (ret and cb_) + { + cb_(ip_type_ == ip_type::IPv6 ? updater_->ddns_ipv6().toString() : updater_->ddns_ipv4().toString(), + ip_type_== ip_type::IPv6 ? updater_->esp_ipv6().toString(): updater_->esp_ipv4().toString()); + } + } + else if (ip_type_ == ip_type::IPv4_and_v6) + { + ret = updater_->update(domain_, token_, ip_type::IPv4, use_local_ip); + if (ret and cb_) + { + cb_(updater_->ddns_ipv4().toString(), updater_->esp_ipv4().toString()); + } + + ret = updater_->update(domain_, token_, ip_type::IPv6, use_local_ip); + if (ret and cb_) + { + cb_(updater_->ddns_ipv6().toString(), updater_->esp_ipv6().toString()); + } + } + + return ret; + } + + String client::get_ipv6() + { + #if defined(ESP32) + auto ip_addr = esp32experimental::globalIPv6(); + + return ip_addr.toString(); + #elif defined(ESP8266) + #if LWIP_IPV6 + for (auto addr : addrList) + { + if (!addr.isLocal() && addr.isV6()) + { + return addr.toString(); + } + } + + return ""; + #endif + #endif + } +} diff --git a/EspDDNS.h b/EspDDNS.h new file mode 100644 index 0000000..c38c9da --- /dev/null +++ b/EspDDNS.h @@ -0,0 +1,183 @@ +/* +MIT License + +Copyright (c) 2023 Amitesh Singh + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#pragma once + +#include +#include +#include + +#if defined(ESP8266) + #include "ESP8266WiFi.h" + #include "ESP8266HTTPClient.h" +#elif defined(ESP32) + #include "WiFi.h" + #include "HTTPClient.h" + #include +#include + +#endif +#if defined(ESP8266) + #if LWIP_IPV6 + #include "lwip/ip_addr.h" + #include + #include + #include "lwip/err.h" + #include "lwip/dhcp.h" + #endif +#endif + +namespace ddns +{ + enum class type + { + DUCKDNS, //duckdns.org + DYNV6, //dynv6.com + }; + + enum class ip_type + { + IPv6, + IPv4, + IPv4_and_v6 + }; + + class updater + { + constexpr const static auto public_ip_finder_url { "http://ifconfig.me/ip" }; + + protected: + + bool dns_success_ = false; + #if defined(ESP8266) + IPAddress esp_ipv6_; + IPAddress duckdns_ipv6_; + #elif defined(ESP32) + IPv6Address esp_ipv6_; + IPv6Address duckdns_ipv6_; + #endif + IPAddress esp_ipv4_; + IPAddress duckdns_ipv4_; + + IPAddress getPublicIPv4(); + void getEspIPv4(bool use_local_ip); + void getEspIPv6(); + void getDDNSIPv4(const String &domain); + void getDDNSIPv6(const String &domain); + + bool connect(const String &url); + + public: +#if defined(ESP8266) + IPAddress &esp_ipv6() + { + return esp_ipv6_; + } + + IPAddress &ddns_ipv6() + { + return duckdns_ipv6_; + } +#elif defined(ESP32) + IPv6Address &esp_ipv6() + { + return esp_ipv6_; + } + + IPv6Address &ddns_ipv6() + { + return duckdns_ipv6_; + } +#endif + IPAddress &esp_ipv4() + { + return esp_ipv4_; + } + + IPAddress &ddns_ipv4() + { + return duckdns_ipv4_; + } + + virtual bool update(const String &domain, const String& token, ip_type, bool) = 0; + virtual ~updater() {} + }; + + class duckdns: public updater + { + public: + bool update(const String &domain, const String &token, ip_type ipt, bool use_local_ip) override; + }; + + class client + { + public: + using cb_t = std::function; + + private: + type type_; + String domain_; + String token_; + ip_type ip_type_; + + cb_t cb_; + updater *updater_; + + public: + client(type t, String &&domain, String &&token, ip_type ipt = ip_type::IPv6): + type_(t), + domain_(std::move(domain)), + token_(std::move(token)), + ip_type_(ipt) + { + if (type_ == type::DUCKDNS) + { + updater_ = new duckdns(); + } + else if (type_ == type::DYNV6) + { + + } + #if defined(ESP32) + if (ip_type_ == ip_type::IPv6) + { + //enable sta ipv6 here + // WiFi.enableIpV6(); + } + #endif + } + + void onUpdate(cb_t cb) + { + cb_ = cb; + } + + bool update(bool use_local_ip = false); + String get_ipv6(); + ~client() + { + delete updater_; + } + }; +} diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..216a713 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Amitesh Singh + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..1690002 --- /dev/null +++ b/README.md @@ -0,0 +1,79 @@ +# EspDDNS + +IPV6 enabled DDNS client for ESP8266 and ESP32. + +## Supported DDNS providers: +- duckdns -> `Fully supported` +- dynv6 -> `In progress` + +This only works if IPv6 is supported by your ISP. [https://test-ipv6.com/](https://test-ipv6.com/) +## esp8266 example +- For IPv6 support in esp8266, enable lwpv2 IP6 low memory option in arduino ide.
+ `Tools->lwIP variant->v2 IP6 low memory` + +``` +#include + +static constexpr const auto ssid { "******" }; +static constexpr const auto passwd { "*****" }; + +void set_dnsserver_google() +{ + //set dns server + ip_addr_t ip6_dns; + // GOOGLE EXTERNAL - 2001:4860:4860::8888 + IP_ADDR6(&ip6_dns,PP_HTONL(0x20014860UL), PP_HTONL(0x48600000UL), + PP_HTONL(0x00000000UL), PP_HTONL(0x00008888UL)); + dns_setserver(0, &ip6_dns); +} + +void setup() +{ + Serial.begin(115200); + WiFi.begin(ssid, passwd); + + while (WiFi.status() != WL_CONNECTED) + { + delay(100); + Serial.print("."); + } + + Serial.print("Connected.., local ip: "); + Serial.println(WiFi.localIP()); + + set_dnsserver_google(); + delay(100); + + // In case of ipv6, do enable lwp2 option in arduino ide. + // IPv6 is by default + //ddns::client ddns_client(ddns::type::DUCKDNS, "yourdomain.duckdns.org", "yourduckdnstoken"); + ddns::client ddns_client(ddns::type::DUCKDNS, "yourdomain.duckdns.org", + "yourduckdnstoken", ddns::ip_type::IPv6); + ddns_client.onUpdate([](String old_ip, String new_ip) { + Serial.print("Ip address is changed to: "); + Serial.print(new_ip); + }); + + //just check once on boot only. + ddns_client.update(); +} + +void loop() +{ +} +``` +## ESP32 +- IPv6 is not fully enabled in ESP32 arduino SDK. You have to compile arduino as a component under `esp-idf`. + +IPV6 must be enabled at esp-idf level: +- `CONFIG_LWIP_IPV6` +- `CONFIG_LWIP_IPV6_AUTOCONFIG=y` +- `CONFIG_LWIP_IPV6_RDNSS_MAX_DNS_SERVERS=2` + +~~Refer [examples/esp32_duckdns_ipv6](examples/esp32_duckdns_ipv6/esp32_duckdns_ipv6.ino)~~ + +Refer to [EspDDNS with esp-idf](https://github.com/amitesh-singh/EspDDNS_with_IDF) + +# Support me + +[!["Buy Me A Coffee"](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://www.buymeacoffee.com/singhamiteK) diff --git a/examples/duckdns_ipv4/duckdns_ipv4.ino b/examples/duckdns_ipv4/duckdns_ipv4.ino new file mode 100644 index 0000000..085fee1 --- /dev/null +++ b/examples/duckdns_ipv4/duckdns_ipv4.ino @@ -0,0 +1,33 @@ +//This example works for both ESP32 and ESP8266 +#include + +static constexpr const auto ssid { "******" }; +static constexpr const auto passwd { "*****" }; + +void setup() +{ + Serial.begin(115200); + WiFi.begin(ssid, passwd); + + while (WiFi.status() != WL_CONNECTED) + { + delay(100); + Serial.print("."); + } + + Serial.print("Connected.., local ip: "); + Serial.println(WiFi.localIP()); + + ddns::client ddns_client(ddns::type::DUCKDNS, "yourdomain.duckdns.org", "yourduckdnstoken", ddns::ip_type::IPv4); + ddns_client.onUpdate([](String old_ip, String new_ip) { + Serial.print("Ip address is changed to: "); + Serial.println(new_ip); + }); + + //just check once on boot only. + ddns_client.update(); +} + +void loop() +{ +} diff --git a/examples/esp32_duckdns_ipv6/esp32_duckdns_ipv6.ino b/examples/esp32_duckdns_ipv6/esp32_duckdns_ipv6.ino new file mode 100644 index 0000000..105abd4 --- /dev/null +++ b/examples/esp32_duckdns_ipv6/esp32_duckdns_ipv6.ino @@ -0,0 +1,86 @@ +// esp32 example +#include "EspDDNS.h" +#include + +static constexpr const auto ssid { "************" }; +static constexpr const auto passwd { "*************" }; + +bool waitFlag = true; +void WiFiEvent(WiFiEvent_t event) +{ + switch(event) { + case ARDUINO_EVENT_WIFI_STA_START: + //set sta hostname here + WiFi.setHostname("espddns-ipv6test"); + break; + case ARDUINO_EVENT_WIFI_STA_CONNECTED: + //enable sta ipv6 here + WiFi.enableIpV6(); + break; + case ARDUINO_EVENT_WIFI_STA_GOT_IP6: + Serial.print("STA IPv6: "); + Serial.println(WiFi.localIPv6()); + waitFlag = false; + break; + default: + break; + } +} + +void set_dnsserver_google() +{ + //set dns server + ip_addr_t ip6_dns; + // GOOGLE EXTERNAL - 2001:4860:4860::8888 + IP_ADDR6(&ip6_dns,PP_HTONL(0x20014860UL), PP_HTONL(0x48600000UL), PP_HTONL(0x00000000UL), PP_HTONL(0x00008888UL)); + dns_setserver(0, &ip6_dns); +} + +void setup() +{ + Serial.begin(115200); + + WiFi.onEvent(WiFiEvent); + WiFi.mode(WIFI_MODE_STA); + WiFi.begin(ssid, passwd); + + set_dnsserver_google(); + delay(100); + + while (WiFi.status() != WL_CONNECTED) + { + delay(100); + Serial.print("."); + } + + ddns::client ddns_client(ddns::type::DUCKDNS, "XXXX.duckdns.org", + "abcde-fdgh-ijh", ddns::ip_type::IPv6); + + Serial.println("Connected.."); + + set_dnsserver_google(); + delay(100); + + ddns_client.onUpdate([](String old_ip, String new_ip) { + Serial.printf("Ip address is changed to %s from %s", new_ip.c_str(), old_ip.c_str()); + }); + + //just check once on boot only. + while (waitFlag) + { + Serial.println("waiting..."); + delay(1000); + } + Serial.println(WiFi.localIP()); + Serial.println(WiFi.localIPv6()); + + // For esp32, this is required. The global ipv6 gets assigned after few seconds since link ipv6 is assigned + delay(5000); + + Serial.printf("global ipv6 address: %s", ddns_client.get_ipv6().c_str()); + ddns_client.update(); +} + +void loop() +{ +} diff --git a/examples/esp8266_duckdns_ipv6/esp8266_duckdns_ipv6.ino b/examples/esp8266_duckdns_ipv6/esp8266_duckdns_ipv6.ino new file mode 100644 index 0000000..c41f33d --- /dev/null +++ b/examples/esp8266_duckdns_ipv6/esp8266_duckdns_ipv6.ino @@ -0,0 +1,49 @@ +#include + +static constexpr const auto ssid { "******" }; +static constexpr const auto passwd { "*****" }; + +void set_dnsserver_google() +{ + //set dns server + ip_addr_t ip6_dns; + // GOOGLE EXTERNAL - 2001:4860:4860::8888 + IP_ADDR6(&ip6_dns, PP_HTONL(0x20014860UL), PP_HTONL(0x48600000UL), + PP_HTONL(0x00000000UL), PP_HTONL(0x00008888UL)); + dns_setserver(0, &ip6_dns); +} + +void setup() +{ + Serial.begin(115200); + WiFi.begin(ssid, passwd); + + while (WiFi.status() != WL_CONNECTED) + { + delay(100); + Serial.print("."); + } + + Serial.print("Connected.., local ip: "); + Serial.println(WiFi.localIP()); + + set_dnsserver_google(); + delay(100); + + // In case of ipv6, do enable lwp2 option in arduino ide. + // IPv6 is by default + //ddns::client ddns_client(ddns::type::DUCKDNS, "yourdomain.duckdns.org", "yourduckdnstoken"); + ddns::client ddns_client(ddns::type::DUCKDNS, "yourdomain.duckdns.org", + "yourduckdnstoken", ddns::ip_type::IPv6); + ddns_client.onUpdate([](String old_ip, String new_ip) { + Serial.print("Ip address is changed to: "); + Serial.print(new_ip); + }); + + //just check once on boot only. + ddns_client.update(); +} + +void loop() +{ +} \ No newline at end of file diff --git a/keywords.txt b/keywords.txt new file mode 100644 index 0000000..8859ede --- /dev/null +++ b/keywords.txt @@ -0,0 +1,4 @@ +ddns KEYWORD1 +client KEYWORD2 +update KEYWORD2 +ip_type KEYWORD2 \ No newline at end of file diff --git a/library.json b/library.json new file mode 100644 index 0000000..e942f45 --- /dev/null +++ b/library.json @@ -0,0 +1,21 @@ +{ + "name": "EspDDNS", + "keywords": "EspDDNS, ddns, duck, duckdns, dynv6", + "description": "IPV6 enabled DDNS client for ESP8266 and ESP32.", + "repository": + { + "type": "git", + "url": "https://github.com/amitesh-singh/EspDDNS" + }, + "authors": + [ + { + "name": "Amitesh Singh", + "email": "singh.amitesh@gmail.com", + "maintainer": true + } + ], + "version": "0.0.1", + "frameworks": "arduino", + "platforms": "espressif" + } diff --git a/library.properties b/library.properties new file mode 100644 index 0000000..f1cd9a6 --- /dev/null +++ b/library.properties @@ -0,0 +1,9 @@ +name=EspDDNS +version=0.0.1 +author=Amitesh Singh +maintainer=Amitesh Singh +sentence=esp8266 and esp32 DDNS client library with IPv6 support +paragraph=A library to implement a DDNS client for esp32 and esp8266. It is currently support duckdns and dynv6. +category=Communication +url=https://github.com/amitesh-singh/EspDDNS +architectures=esp8266,esp32 \ No newline at end of file