Duck DDNS cho ESP32

Duck DDNS trên ESP32 subdomain giá rẻ cho mọi người.

Duckdns cho tạo 5 sub miễn phí đăng ký đơn giản bằng tài khoản google, github… lợi dụng điều này ta sẽ lấy subdomain miễn phí( mất phí phần cứng tối thiểu) để cập nhật publicIP ở nhà thay cho các dịch vụ ddns có tính phí khác bằng cách nạp code cho board esp32.

Với subdomain này khỏi mua ip tĩnh, dyndns, noip,… có thể dùng để kéo onvif cho imou, ezviz,… miễn phí tới khi duckdns đóng dịch vụ này thì ta chuyển qua thằng khác.

1.Chuẩn bị: ESP32 giá 50cành bấm vào xem board dùng nếu nạp đúng code này.

2.Cài Arduino IDE và cài 1 số thư viện nếu quá trình chạy code báo lỗi, nếu chưa biết cài thì cứ google.

Trước khi nạp code cần tạo acc Duckdns ,reg tên miền tránh trường hợp reg tên miền không được vì bị trùng với người khác.

 

Code: copee code phía dưới. cho vào Arduino IDE.

#include <WiFi.h>
#include <HTTPClient.h>
#include <Wire.h>
#include <RTClib.h>

const char* ssid = "mixxxxx";
const char* password = "1234567999";
const char* duckDNS_domain = "subdomain4";
const char* duckDNS_token = "xxx0bd9-ef52-4846-bd17-xxxxxxxx";
RTC_DS3231 rtc;

const int ledPin = 15; // Sử dụng chân GPIO15 để điều khiển LED
const int MAX_CONNECTION_ATTEMPTS = 3; // Số lần thử kết nối lại WiFi tối đa
const int WIFI_RETRY_INTERVAL = 7000; // Thời gian chờ giữa các lần thử kết nối lại WiFi (7 giây)
const int DDNS_UPDATE_INTERVAL = 60000; // Thời gian giữa các lần cập nhật DDNS (1 phút)
const unsigned long LIGHT_CYCLE_DURATION = 500; // Thời gian một chu kỳ sáng tắt là 1 giây
const unsigned long LIGHT_ON_DURATION = 500; // Thời gian sáng là 0.5 giây
const unsigned long RESTART_INTERVAL = 43200000; // Thời gian giữa các lần khởi động lại (12 giờ)

bool isWifiConnected = false;
bool isAttemptingConnection = false;
int wifiConnectionAttempts = 0;
unsigned long lastCycleTime = 0;
unsigned long lastDDNSUpdateTime = 0;
unsigned long lastRestartTime = 0;
void updateDDNS();
void checkWifiConnection();
void controlLED();
void restartESP32();

void setup() {
 Serial.begin(115200);

 pinMode(ledPin, OUTPUT); // Đặt chân GPIO để điều khiển đèn là đầu ra

 // Khởi động kết nối
 Wire.begin();

 // Khởi động kết nối tới mạng WiFi
 WiFi.begin(ssid, password);
 Serial.print("Connecting to WiFi");
 checkWifiConnection();
 updateDDNS();
 lastRestartTime = millis(); // Gán thời gian khởi đầu cho biến lastRestartTime
}
void loop() {
 // Chạy hàm kiểm tra kết nối WiFi mỗi lần
 checkWifiConnection();
 // Kiểm tra và điều khiển trạng thái LED
 controlLED();
 // Kiểm tra và khởi động lại ESP32 hàng ngày
 if (millis() - lastRestartTime >= RESTART_INTERVAL) {
 restartESP32();
 }
// Cập nhật DDNS mỗi phút nếu đã kết nối và đã đến thời gian cập nhật
 if (isWifiConnected && millis() - lastDDNSUpdateTime >= DDNS_UPDATE_INTERVAL) {
 updateDDNS();
 lastDDNSUpdateTime = millis();
 }
}
void controlLED() {
 unsigned long currentMillis = millis();

 // Kiểm tra nếu đã đến thời gian cho một chu kỳ mới
 if (isWifiConnected && (currentMillis - lastCycleTime >= LIGHT_CYCLE_DURATION)) {
 lastCycleTime = currentMillis;
 // Nếu có kết nối WiFi, sáng LED và bỏ qua điều kiện chớp tắt ban đầu
 digitalWrite(ledPin, HIGH);
 return;
 }
 // Kiểm tra nếu LED cần được tắt
 if (currentMillis - lastCycleTime >= LIGHT_ON_DURATION) {
 digitalWrite(ledPin, LOW);
 } else {
 digitalWrite(ledPin, HIGH); // Bắt đầu với trạng thái sáng LED
 }
}
void checkWifiConnection() {
 if (WiFi.status() != WL_CONNECTED) {
 // Nếu mất kết nối WiFi
 isWifiConnected = false;
 // Nếu không phải là lần thử kết nối lại
 if (!isAttemptingConnection) {
 // Bắt đầu quá trình thử kết nối lại
 isAttemptingConnection = true;
 wifiConnectionAttempts = 0;
 }
 // Kết nối lại WiFi nếu cần thiết và chưa vượt quá số lần thử tối đa
 if (isAttemptingConnection && wifiConnectionAttempts < MAX_CONNECTION_ATTEMPTS) {
 if (millis() - lastCycleTime >= WIFI_RETRY_INTERVAL) {
 wifiConnectionAttempts++;
 Serial.print("Attempting to reconnect to WiFi (Attempt ");
 Serial.print(wifiConnectionAttempts);
 Serial.println(")");
 WiFi.begin(ssid, password);
 lastCycleTime = millis();
 }
 } else {
 isAttemptingConnection = false;
 Serial.println("WiFi connection failed after multiple attempts.");
 digitalWrite(ledPin, LOW); // Nhấp nháy LED khi kết nối WiFi thất bại
 }
 } else {
 isWifiConnected = true;
 isAttemptingConnection = false;
 wifiConnectionAttempts = 0; 
 updateDDNS();
 }
}
void updateDDNS() {
 String duckDNS_update_url = "http://www.duckdns.org/update?domains=" + String(duckDNS_domain) + "&token=" + String(duckDNS_token) + "&ip=";
 HTTPClient http;
 http.begin("https://ipv4.icanhazip.com");
 int httpCode = http.GET();
 String currentIP = "";
 if (httpCode == HTTP_CODE_OK) {
 currentIP = http.getString();
 Serial.println("Current IP: " + currentIP);
 HTTPClient httpUpdate;
 httpUpdate.begin(duckDNS_update_url + currentIP);
 int httpUpdateCode = httpUpdate.GET();
 if (httpUpdateCode == HTTP_CODE_OK) {
 Serial.println("DDNS update success");
 }
 httpUpdate.end();
 } else {
 Serial.println("Failed to connect to IP service");
 }
 http.end();
}
void restartESP32() {
 Serial.println("Restarting ESP32...");
 ESP.restart();
}

 

sửa thông tin sau theo ý bạn:

const char* ssid = “tên wifi”;
const char* password = “mật khẩu wifi”;
const char* duckDNS_domain = “subdomain4”;
const char* duckDNS_token = “xxx0bd9-ef52-4846-bd17-xxxxxxxx”;

Cắm board vào và nạp tạo 1 tên wifi 2.4g với thông tin đã đặt và tận hưởng.Trong code mình sử dụng chân LED trên board làm báo hiệu trạng thái hoạt động và đã chú thích khá nhiều nên chắc dễ hiểu nhỉ.

duck0

Vì là fix cứng wifi, passwd, subdomain, token. nên khá bất tiện yêu cầu phải có  máy tính hoặc sài điện thoại cài Arduino Studio – Arduino IDE cái nạp tên điện thoại mình chưa thử. và do  giá rẻ nên phải bỏ công làm.

Mình đang viết lại để có thể thay đổi thông như hình dưới có nạp từ xa khi mở port, có thêm ddns của swanndvr.net thằng này cũng tạo được 6 subdomain miễn phí. dù cách nào đi nữa ban đầu vẫn phải nạp code cho esp32 rồi mới nạp từ xa được.

 

duck

Dưới đây là phần giải thích sơ về đoạn mã Arduino trên:

Thư viện

– `#include <WiFi.h>`: Thư viện cho kết nối WiFi.
– `#include <HTTPClient.h>`: Thư viện cho việc thực hiện các yêu cầu HTTP.
– `#include <Wire.h>`: Thư viện cho giao tiếp I2C.
– `#include <RTClib.h>`: Thư viện cho việc sử dụng Real-Time Clock (RTC).

Biến toàn cục

– `const char* ssid = “mixxxxx”;`: Tên SSID cho mạng WiFi.
– `const char* password = “1234567999”;`: Mật khẩu cho mạng WiFi.
– `const char* duckDNS_domain = “subdomain4”;`: Tên miền DuckDNS.
– `const char* duckDNS_token = “xxx0bd9-ef52-4846-bd17-xxxxxxxx”;`: Token DuckDNS để cập nhật địa chỉ IP.
– `RTC_DS3231 rtc;`: Đối tượng RTC sử dụng DS3231.

Các biến cấu hình và trạng thái

– `const int ledPin = 15;`: Pin GPIO15 được sử dụng để điều khiển đèn LED.
– `const int MAX_CONNECTION_ATTEMPTS = 3;`: Số lần thử kết nối lại WiFi tối đa.
– `const int WIFI_RETRY_INTERVAL = 7000;`: Thời gian chờ giữa các lần thử kết nối lại WiFi (7 giây).
– `const int DDNS_UPDATE_INTERVAL = 60000;`: Thời gian giữa các lần cập nhật DDNS (1 phút).
– `const unsigned long LIGHT_CYCLE_DURATION = 500;`: Thời gian một chu kỳ sáng tắt là 1 giây.
– `const unsigned long LIGHT_ON_DURATION = 500;`: Thời gian sáng là 0.5 giây.
– `const unsigned long RESTART_INTERVAL = 43200000;`: Thời gian giữa các lần khởi động lại (12 giờ).

– `bool isWifiConnected = false;`: Biến trạng thái kết nối WiFi.
– `bool isAttemptingConnection = false;`: Biến trạng thái thử kết nối lại WiFi.
– `int wifiConnectionAttempts = 0;`: Số lần thử kết nối lại WiFi.
– `unsigned long lastCycleTime = 0;`: Thời gian của chu kỳ đèn LED cuối cùng.
– `unsigned long lastDDNSUpdateTime = 0;`: Thời gian cập nhật DDNS lần cuối.
– `unsigned long lastRestartTime = 0;`: Thời gian khởi động lại lần cuối.

Hàm `setup()`

– `Serial.begin(115200);`: Khởi động giao tiếp serial với tốc độ 115200 baud.
– `pinMode(ledPin, OUTPUT);`: Thiết lập pin GPIO15 làm đầu ra để điều khiển đèn LED.
– `Wire.begin();`: Khởi động giao tiếp I2C.
– `WiFi.begin(ssid, password);`: Bắt đầu kết nối đến mạng WiFi.
– `checkWifiConnection();`: Kiểm tra và kết nối lại WiFi nếu cần.
– `updateDDNS();`: Cập nhật địa chỉ IP lên DuckDNS.
– `lastRestartTime = millis();`: Gán thời gian khởi đầu cho biến `lastRestartTime`.

Hàm `loop()`

– `checkWifiConnection();`: Kiểm tra trạng thái kết nối WiFi và kết nối lại nếu cần.
– `controlLED();`: Điều khiển trạng thái đèn LED.
– `if (millis() – lastRestartTime >= RESTART_INTERVAL)`: Kiểm tra và khởi động lại ESP32 sau khoảng thời gian đã định.
– `if (isWifiConnected && millis() – lastDDNSUpdateTime >= DDNS_UPDATE_INTERVAL)`: Cập nhật địa chỉ IP lên DuckDNS nếu đã kết nối WiFi và đã đến thời gian cập nhật.

Hàm `controlLED()`

– `unsigned long currentMillis = millis();`: Lấy thời gian hiện tại.
– `if (isWifiConnected && (currentMillis – lastCycleTime >= LIGHT_CYCLE_DURATION))`: Kiểm tra và điều khiển đèn LED nếu đã kết nối WiFi.
– `if (currentMillis – lastCycleTime >= LIGHT_ON_DURATION)`: Tắt đèn LED nếu đã đến thời gian tắt.

Hàm `checkWifiConnection()`

– `if (WiFi.status() != WL_CONNECTED)`: Kiểm tra trạng thái kết nối WiFi.
– `if (!isAttemptingConnection)`: Bắt đầu thử kết nối lại nếu chưa thực hiện.
– `if (isAttemptingConnection && wifiConnectionAttempts < MAX_CONNECTION_ATTEMPTS)`: Thử kết nối lại WiFi nếu chưa vượt quá số lần thử tối đa.
– `WiFi.begin(ssid, password);`: Kết nối lại WiFi.
– `if (WiFi.status() == WL_CONNECTED)`: Cập nhật địa chỉ IP lên DuckDNS nếu kết nối WiFi thành công.

Hàm `updateDDNS()`

– `HTTPClient http;`: Tạo đối tượng HTTPClient để gửi yêu cầu HTTP.
– `http.begin(“https://ipv4.icanhazip.com”);`: Gửi yêu cầu GET để lấy địa chỉ IP hiện tại.
– `int httpCode = http.GET();`: Lấy mã trạng thái HTTP.
– `if (httpCode == HTTP_CODE_OK)`: Nếu yêu cầu thành công, lấy địa chỉ IP hiện tại và cập nhật lên DuckDNS.

Hàm `restartESP32()`

– `Serial.println(“Restarting ESP32…”);`: In thông báo khởi động lại ESP32.
– `ESP.restart();`: Khởi động lại ESP32.

Tổng kết

Đoạn mã trên kết nối ESP32 tới mạng WiFi, cập nhật địa chỉ IP lên DuckDNS, điều khiển đèn LED báo hiệu trạng thái kết nối WiFi, và khởi động lại ESP32 sau khoảng thời gian đã định. Chương trình cũng xử lý việc kiểm tra và kết nối lại WiFi nếu mất kết nối và thực hiện cập nhật DDNS định kỳ.

 

Leave a Comment

👈 Vuốt để chuyển bài 👉

KIỂM TRA PORT

IPv6 của bạn: Đang lấy...