How to update IP with Arduino uno using DynDns

Hi guys, I have been searching for 2 days trying to figure out how to update DynDNS using an arduino.

I finally cracked it by searching all over the place and combining code from different sources.

so i though i would share the completed and tested working code with the community.

This was updated using IDE 1.8.1
An original arduino UNO and Ethernet shield with the standard library’s were used, nothing special.

The reason for this is i have a BT modem which does not have a static ip address or allow the functionality of auto update of a DDNS account.

/*
 Web client to detect WAN IP address of the arduino and update DynDNS

 Dyn offers a free web IP detection tool: https://help.dyn.com/remote-access-api/checkip-tool/
 Arduino check IP here: http://checkip.dyndns.com:8245/
 Answer received: <html><head><title>Current IP Check</title></head><body>Current IP Address: 93.91.152.138</body></html>
 
 Circuit:
 * Arduino UNO
 * Ethernet shield attached

 created 18 Jan 2016
 by Petr Hubacek, RobotPlace

 Updated 13 Mar 2017
 John Smith - Easy2pc Ltd
 Tested on Arduino IDE 1.8.1

*/

#include <SPI.h>
#include <Ethernet.h>

//****** TO MODIFY **************/
byte mac[] = { 0x00, 0x2B, 0xBE, 0xAE, 0xFE, 0x1D };
String robotName = "Web client get WAN IP from checkip.dyndns.org";
String sourceCode = "";
String robotOwner = "";
//***** TO MODIFY ***************/
//--------- New Variables -----------/
String ip_address     = "";           //newly read ip address from _ip
String ip_address_old  = "";          // old ip address used for comparison
char match_fail = 0;                   // match failure = true
int delay_value = 30000; // 7200000 = 2 hours  //frequency to check ext IP  
byte domaindydns[]= { 204, 13, 248, 112 }; // members.dyndns.org
char hostname[ ]   = "**********.dyndns.org"; // put your hostname here
char userpwdb64[ ] = "*****************";  //http://www.functions-online.com/base64_encode.html    use->   username:password
// the above bit caught me out you have to put your username:password in the box and encode the whole lot.
//-----------------------------------/

// use DNS or the numeric IP for the server:
// answer {"ip":"93.91.152.138"}";
IPAddress server(216, 146, 43, 70);       // numeric IP for checkip.dyndns.org (no DNS)
// char server[] = "http://checkip.dyndns.org"; // name address for checkip.dyndns.org (using DNS)

// Initialize the Ethernet client library
EthernetClient client;

EthernetClient clientdyn;

String readBuffer = "";

void setup()
{
  Serial.begin(57600);
  Serial.println(F("----- SETUP START ------"));
  //Serial.print(F("robotName = "));
  //Serial.println(robotName);
  //Serial.print(F("codebender source = "));
  //Serial.println(sourceCode);

  Serial.print(F("MAC: "));
  for(int i = 0; i < 6 ; i++)
  {
    Serial.print(mac[i], HEX);
    if(i < 5) Serial.print(F("."));
  }
  Serial.println();

  Serial.print(F("DHCP: "));
  // --------------- start the Ethernet connection using DHCP: -----------------
  if (Ethernet.begin(mac) == 0)
  {
    Serial.println(F("DHCP Failed"));
    Serial.println(F("Board stops"));
    // no point in carrying on, so do nothing forevermore:
    for(;;)
      ;
  }

  // --------------- give the Ethernet shield a second to initialize: -------------------
  delay(1000);
  
  Serial.print(F("LAN IP: "));
  for(int i = 0; i < 4 ; i++)
  {
    Serial.print(Ethernet.localIP()[i]);
    if(i < 3) Serial.print('.');
  }
  Serial.println();

  
}
//----------------- Main Loop -----------------------------------------------
void loop()
{
 
 Serial.println("-------------- get_wan_ip --------------");
 get_wan_ip();

Serial.print("String ip_address: ");
Serial.println(ip_address);
Serial.print("String ip_address_old: ");
Serial.println(ip_address_old);

Serial.println("-------------- check_for_difference --------------");
check_for_difference();

//delay (60000);

delay(delay_value);

}

//----------------------------------------------------------------
void get_wan_ip() // Get Public WAN ip address
{
  
  Serial.print(F("connecting..."));

  // if you get a connection, report back via serial:
  if(client.connect(server, 8245))              // you can use port 80, but this works faster
  {
    Serial.println(F("Connected OK"));
    client.println("GET / HTTP/1.0");           // Make a HTTP request:
    client.println("Host: checkip.dyndns.org");
    client.println("Connection: close");
    client.println();

    //********************************
    String _ip = "0";                           //wait until a client is available

    while ( _ip == "0" || millis() < 10000 )
    {
      if (client.available())                   // read incoming bytes available from the server
      {
        delay(10);                              //give time to receive whole message to the buffer
        while (client.available())
        {
          char c = client.read();
          readBuffer += c;
          Serial.print(c);

          if (readBuffer.length() > 100)
          {
            readBuffer = readBuffer.substring(70, readBuffer.length());
          }
        }
        int pos_start = readBuffer.indexOf("IP Address") + 12; // add 10 for "IP Address" and 2 for ":" + "space"
        int pos_end = readBuffer.indexOf("</body>", pos_start); // add nothing
        _ip = readBuffer.substring(pos_start, pos_end);
        Serial.print(F("WAN IP: "));
        Serial.println(_ip);
        ip_address=_ip;                         // put the read ip address into the variable ip_address
        readBuffer = "";
        client.stop();
      }
    }
  }
  else
  {
    Serial.println("failed");                   // no connection to the server:
  }
  Serial.println(F("SETUP end"));
  
}

//-----------------------------------------------------------------------------------------
void check_for_difference()
{
  Serial.println(); 
  
  { if (ip_address != ip_address_old)           // compare the new and old readings
    { match_fail = 1; 
    }//end if 
    else  
     match_fail = 0; 
   
  if (match_fail == 1)  
  { Serial.println("DOES NOT MATCH");  
    update_dyndns();                            // Call the update void update_dyndns()
    ip_address_old = ip_address;
  } 
  else  
  { Serial.println("MATHCHES"); 
    Serial.println(" No Update Required "); 
  } 
  Serial.println();  
  
  }
}
//-----------------------------------------------------------------------------------------
void update_dyndns()
{
  int timeout=0;
  Serial.println("----------- UPDATING DYN DNS -------------");
  Serial.print("connecting to ");
  Serial.println(ip_to_str(domaindydns));
 
  Serial.print("IP to push to DynDns: ");
  Serial.println(ip_address);  
 
if (clientdyn.connect(domaindydns, 80)) {
    Serial.println("connected");
    clientdyn.print("GET /nic/update?hostname=");
    clientdyn.print(hostname);
    clientdyn.print("&myip=");
    clientdyn.print(ip_address);
    clientdyn.println(" HTTP/1.0 ");
    clientdyn.print("Host: ");                            //clientdyn.println("Host: members.dyndns.org ");
    clientdyn.println(ip_to_str(domaindydns));
 
    clientdyn.print("Authorization: Basic ");
    clientdyn.println(userpwdb64);
 
    clientdyn.println("User-Agent: futura - arduinodydns - 1.1");
    clientdyn.println();
  } else {
    Serial.println("connection failed");
  }
 
    delay(1000);
 
  while (!clientdyn.available() && timeout<50) 
  {
    timeout++;
    Serial.print("Time out ");
    Serial.println(timeout);
    delay(100);
  }
 
  while (clientdyn.available()) 
  {
      if (clientdyn.available()) 
      {
        char c = clientdyn.read();
        Serial.print(c);
      }
  }
 
  if (!clientdyn.connected()) 
  {
        Serial.println();
        Serial.println("disconnecting.");
        clientdyn.stop();
  }
 
}
 
// This is just a little utility function to format an IP address as a string.
const char* ip_to_str(const uint8_t* ipAddr)
{
  static char buf[16];
  sprintf(buf, "%d.%d.%d.%d\0", ipAddr[0], ipAddr[1], ipAddr[2], ipAddr[3]);
  return buf;
}

I hope its useful to someone else.

Any comments good or bad let me know.

String robotName = "Web client get WAN IP from checkip.dyndns.org";
String sourceCode = "";
String robotOwner = "";

Why do you need to piss away resources using Strings? There is NOTHING that a String can do that can't be done quite easily using char arrays.

int delay_value = 30000; // 7200000 = 2 hours  //frequency to check ext IP

Do you REALLY need to check every 30 seconds?

I welcome the constructive criticism, you are more than welcome to modify the code as you see fit.

I welcome you to improve upon what has been created, but please don't give a blanket statement without first, at least improving the code.

We are all here to learn, and if you have forgotten that, then shame on you.

yes 30 seconds is a bit fast and that was an oversight on my behalf, it was originally set to 7200000 2rs as can be seen in the code you so graciously posted.

John. :sob:

yes 30 seconds is a bit fast and that was an oversight on my behalf, it was originally set to 7200000 2rs as can be seen in the code you so graciously posted.

And, does 7200000 fit in an int? On all Arduinos?

PaulS: And, does 7200000 fit in an int? On all Arduinos?

I have no clue if it does or not, that is why i clearly stated i used an UNO in the build.

I'm sure you will clarify for us won't you ???

I'm sure you will clarify for us won't you

No. I expect you to be able to determine something so basic. What I will do is point you to the documentation: https://www.arduino.cc/en/Reference/Int

PaulS: No. I expect you to be able to determine something so basic. What I will do is point you to the documentation: https://www.arduino.cc/en/Reference/Int

Hi Paul

int would not be suitable for the value, perhaps using long might be a better fit, what do you think am i heading in the right direction.

john.

just dropping a thanks to easy2pc

a nicer solution on ESP32 here >

https://github.com/ayushsharma82/EasyDDNS

Curious that you’re connecting this directly to the ‘internet’ without a router in the middle. If it’s on the 3G/4G network, you may find the carrier needs to join the conversation so your IP address will stay relatively static. If there is a router in your mix - wifi AP etc, then do your DDNS in that, and port—forward the traffic to your local host.

EDIT... What does your BT modem connect to?