venerdì 25 novembre 2016

Risoluzione IP Dinamico con Arduino




La maggior parte delle connessioni domestiche a Internet avviene con un IP dinamico fornito dal provider all'atto di ciascuna connessione. Per consentire l'accesso remoto a dispositivi IoT e applicazioni di domotica si ricorre a servizi DDNS semprechè il modem ADSL li supporti. Inoltre la maggioranza dei servizi è ora a pagamento. Il metodo alternativo qui presentato utilizza una scheda Arduino con shield Ethernet per mantenere aggiornato su un server l'indirizzo IP corrente in un file testo. Una semplice pagina .php consente sia di ridirigere una connessione client HTTP alla rete domestica (all'IP corrente) che di aggiornare il file testo contenente l'indirizzo.
Arduino periodicamente aquisisce l'IP corrente e aggiorna il file testo sul server chiamando la pagina .php passando il parametro "newip"; digitando da un qualunque browser in rete l'indirizzo della pagina .php (con password) si viene ridiretti all'IP dinamico e quindi alla nostra rete domestica.


----------------------------------------------------------------
<?php

$file = "ip.txt";

if(isset($_GET['newip']) == true && isset($_GET['pass']) == true)
{
   $ip = $_GET['newip'];
   $pass = $_GET['pass'];

   if($pass == "abc123")
   {
      file_put_contents($file, $ip);
   }
}
else if(isset($_GET['pass']) == true)
{
   $pass = $_GET['pass'];
   if($pass == "abc123")
   {
      // get IP address
      $port = $_GET['port'];
      $ip = file_get_contents($file);
      echo '<html>';
      echo '<head>';
      echo '<meta http-equiv="refresh" content="0; url=http://'.$ip.':'.$port.'" />';
      echo '</head>';
      echo '<body>';
      echo '</html>';
   }
}
?>

----------------------------------------------------------------

Il codice completo dello sketch per Arduino è scaricabile qui. E' previsto l'utilizzo di uno shield economico basato sul chip ENC28J60.

Il loop principale è riportato qui di seguito:

void loop() {
 ether.packetLoop(ether.packetReceive());
 switch(actual_status) {
  case STATUS_IDLE: getIP(); break;
  case STATUS_WAIT_IP: waitIP(); break;
  case STATUS_SEND_IP: sendIP(); break;
  case STATUS_WAIT_RESP: waitRESP(); break;
  }
}

L'invio delle richieste client avviene con la funzione ether.browseUrl della libreria EtherCard.h

ether.browseUrl(PSTR("/"), pageurl , setipwebsite, setip_callback);

Credits:
L'idea originale è derivata da un post sul web di Gianluca Ghettini, in cui l'aggiornamento del file testo avviene con uno script bash (che però necessita di un sistema Linux). La pagina .php è stata modificata con l'aggiunta del parametro "port" per accedere a uno specifico server web all'interno della rete domestica (es. IPcam, termostato, ecc.).