Pido consejos sobre la forma de conectar arduino a través de Inetenet

Quizá mi consulta sale un poco del campo del arduino, pero está muy relacionada, tal vez alguien pueda ayudarme.

Tengo un arduino que controla algunas luces, y tiene un servidor web por medio del cual se dan las órdenes. Funciona perfectamente: desde una computadora o celular entro a la web del arduino (http://192.168.0.10) y obtengo información y doy órdenes, todo muy bien, está funcionando perfectamente.

El problema que tengo es que solamente puedo acceder a esa página desde la misma red, es decir, estando dentro de la casa, y quiero poder acceder a través de Internet, desde cualquier lugar. (Sé que teniendo una IP accesible desde internet podría lograrlo sin problemas, pero eso no es posible porque el servicio de internet que tengo no brinda esa opción, y ocurre lo mismo en miles de conexiones similares, en miles de casas).

Quiero solicitar consejos sobre la forma de solucionar esto.

Gracias

Una solución que se me ocurrió es usar un servidor, pues justamente cuento con uno que está siempre encendido, y por supuesto, tiene una IP accesible: Mi idea es que el arduino debería conectarse a ese servidor a través de internet, y mantener esa comunicación abierta (conectarse cuando se enciende, y cada cierto tiempo reconectarse, por si se pierde la conexión). Desde cualquier sitio (a través de internet) yo podría entrar a una web del servidor, entonces, al recibir esa conexión, el servidor se debería comunicarse con el arduino (dado que la comunicación está abierta), esperar la respuesta y retransmitirla al cliente web. ¿Es correcta esta solución? ¿O estoy muy desenfocado?

Si es correcta la solución, también quería pedir consejos sobre el programa que debería usar en el servidor para hacer esta mediación. El servidor con el que cuento es windows server 2012, con apache y php. Quería pedir consejos sobre qué lenguaje debería usar para hacer el programa que permita hacer de intermediario con Arduino, según la idea que expuse arriba.

Muchas gracias de antemano.

Tienes que hacer un port forward en tu router para habilitar esa dirección local y hacerla pública pero al hacerlo, tienes la obligación de poder UBICAR tu dirección publica. Para ello se usan algunos programas que verifican cual es tu dirección y convierten tu DNS dinámico en digamos fijo (aunque no lo es) facilmente alcanzable desde el exterior, a menos que tengas una ip fija contratada con tu proveedor y todo esto no tiene sentido.

Cualquier Host DNS te va a servir, yo uso no-ip que es gratis y cada 30 dias tienes que renovar tu suscripcion.
Hay otros claro.

Yo antes usaba noip.com, pero ahora uso https://www.duckdns.org/

Con la segunda opción te olvidas de tener que estar actualizando cada 30 días.

Pero sin el port forward de nada sirve el duck DNS que uses.
Al router le debes decir via port forward que cada vez que llegue una petición externa la canalice via la ip local.

Hola,
Otra forma es consultar cual es tu ip publica, ademas de esta primera consulta, periodicamente hay que comprobar si la ip publica ha cambiado. En mi caso, si ha cambiado la ip, me manda un correo/whatsapp con la nueva IP. Os pongo el trozo de codigo que obtiene la ip publica.

void GetExternalIP(){
  //Serial.end();
  WiFiClient client;
  String str;
  String tmpPub2;
  if (!client.connect("api.ipify.org", 80)) {
    //Serial.println("Failed to connect with 'api.ipify.org' !");
  }
  else {
    int timeout = millis() + 5000;
    client.print("GET /?format=json HTTP/1.1\r\nHost: api.ipify.org\r\n\r\n");
    while (client.available() == 0) {
      if (timeout - millis() < 0) {
        //Serial.println(">>> Client Timeout !");
        client.stop();
        return;
        break;
      }
    }
    int size;
    while ((size = client.available()) > 0) {
      uint8_t* msg = (uint8_t*)malloc(size);
      size = client.read(msg, size);
      //Serial.write(msg, size);
      str = (char*)msg;
      free(msg);
      delay(20);
    }
    //Serial.println(str);
    int indiceParametro = str.indexOf('ip\":\"');
    String tmpPub1 = str.substring(indiceParametro+6);
    indiceParametro = tmpPub1.indexOf('\"}');
    tmpPub2 = String(tmpPub1.substring(0, indiceParametro-1));
              //MensajeDue="ipPublica=                ;";
     Serial2.write("ipPublica=                ;");
     MensajeDue="";
     MensajeDue="ipPublica="+ipPublica+";";
     Serial2.write(MensajeDue.c_str());
    if (ipPublica !=tmpPub2){
      cambioIPPub=true;
      ipPublica=tmpPub2;
      mandarCorreo();
    }

  }

}

Para el envio del correo utilizo la libreria Gsender.h
El envio por whatsapp es algo mas complejo.
Ademas, como comenta surbyte, hay que abrir los puertos del router.

Pero para eso está noip y duckdns, automáticamente hacen ellos los cambios cada vez que tu IP pública cambia y te olvidas de ello.

Muchas gracias por las respuestas.

Alguna vez supe que en algunos países se tiene la posibilidad de hacer lo que indican, creo que en España es posible, y sabía también de Argentina. Pero en mi país no es posible (ignoro como es en otros países). En mi país, todas las compañías conectan el internet con una red interna de la compañía, creo que es por nodos. No sé la forma exacta como lo hacen, pero es algo parecido a NAT. Entonces, la IP que asignan, tanto al módem o enrutador, como a los equipos que se conectan, es completamente inaccesible desde afuera. Supe que en Argentina asignan al enrutador una IP, que es una IP pública, y se puede acceder desde cualquier punto de internet a esa IP. Tan solo al reiniciar el enrutador cambia la ip, pero la nueva sigue siendo accesible. Creo que en España es similar. Pero en mi país es totalmente diferente.

Me estoy embarcando a hacer un programa para el servidor, como describí mas arriba. Este método servirá en cualquier lugar, incluido en lugares que tengan IP accesible (sin necesidad de manipular el enrutador. Aunque la verdad no creo que nunca lo use fuera de mi país). Pienso que la idea no está muy desenfocada, creo que funcionará, pues es un sistema similar al que usan muchos sistemas de comunicación, como por ejemplo (guardando las distancias), whatsapp, teamviewer y muchos otros. Recién intentaré los primeros pasos.

Puedes idear algo que haga lo que dices, pero ¿Para que?, ya está inventado.

Yo adaptaría el código para usar MQTT sobre un servidor en internet, hay varios que dan cuentas gratuitas.
El arduino se encarga de mantener abierta la conexión con el servidor y los clientes leen y/o escriben en el servidor.

Saludos.

Me interesa mucho esto que indicas. ¡Muchas gracias!
En cuanto llegue a casa me pongo a buscar y revisar sobre MQTT .

Lo que utiliza tu operador es CG-NAT y compartes IP publica con mas personas por lo que no puedes abrir puertos.
Depende para que lo vayas a usar, yo uso Blynk que no necesitas abrir puertos, tienes incluso una app gratuita pero limitada.
Uso los pins virtuales modificandolos via IFTTT para obtener valores en nodeMCU.