Revisar conexión a internet

  • 9 Respuestas
  • 193 Vistas

EBD

  • Aprendiz
  • **
  • Mensajes: 36
Revisar conexión a internet
« : mayo 26, 2020, 10:50:41 am »
Buenos días,
Nosotros tenemos varios plc Stx-8091 en distintas máquinas que, utilizando un router con chip 3G, nos posibilita a ver el web server de forma remota y recibir mails del plc al ocurrir una falla en la máquina.

Sin embargo, tenemos el problema de que por momentos el router se queda sin internet y no es posible comunicarnos con el plc. Por esta razón es imposible comandar al plc y la única forma de retomar la conexión es reseteando el router.

Queríamos saber si existe la funcionalidad del plc de revisar periódicamente que la conexión a internet sea estable para que, en caso de que no lo sea, el plc pueda reiniciar el router a través de una de sus salidas a relé.

Aguardo comentarios sobre cómo se podría implementar esto en lenguaje Pawn.

Muchas gracias.

Soporte

  • Global Moderator
  • Experto
  • *****
  • Mensajes: 2160
  • Soporte Técnico
Re:Revisar conexión a internet
« Respuesta #1 : mayo 26, 2020, 11:58:37 am »
Queríamos saber si existe la funcionalidad del plc de revisar periódicamente que la conexión a internet sea estable para que, en caso de que no lo sea, el plc pueda reiniciar el router a través de una de sus salidas a relé.

Buenos días.

Se me ocurre que podés intentar "resolver" u obtener la IP de un hostname, por ejemplo "www.google.com", si la resolución es exitosa, es porque hay internet. Podés hacerlo cada 10 o 30 minutos por ejemplo.

La función para realizar esto es: ResolvLookUp(const Hostnane[], IpAddr, Opt):

Ver manual www.slicetex.com/hw/stx8xxx/docs/STX8XXX-MP-PLC.pdf

Ejemplo:

Atención: No utilizar este ejemplo, ver ejemplo de mensaje foro.slicetex.com/index.php?topic=462.msg2426#msg2426

Código: [Seleccionar]

CheckInternetIsOK()
{
   new Ip
   new Stat

   // Resolver nombre y esperar IP.
   while(Stat == 0)
   {
      Stat = ResolvLookUp("www.google.com", Ip, RESOLV_OPT_FORCE)
   }

   // Comprobar si el nombre pudo ser resuelto.
   if(Stat == 1)
   {
       // Nombre resuelto, hay internet.
       return 1
   }
   else
   {
      // No se pudo resolver nombre, no hay internet.
      return 0
   }
}

Si la función CheckInternetIsOK() devuelve "1", es porque hay conexión a internet.

Notar que ResolvLookUp() utiliza un tercer argumento RESOLV_OPT_FORCE que es para forzar la resolución de nombre y no utilizar tablas internas de caché.

Esta operación puede tardar algunos segundos ya que intenta realizar conexión al servidor y esperar repuesta.

Saludos!.
« Última Modificación: mayo 27, 2020, 21:14:49 pm por Soporte »
SOPORTE TÉCNICO

Slicetex Electronics
www.slicetex.com

EBD

  • Aprendiz
  • **
  • Mensajes: 36
Re:Revisar conexión a internet
« Respuesta #2 : mayo 26, 2020, 12:24:28 pm »
Perfecto, lo intentaré agregar al programa en estos días. Cualquier problema que surja te aviso. Muchas gracias.

EBD

  • Aprendiz
  • **
  • Mensajes: 36
Re:Revisar conexión a internet
« Respuesta #3 : mayo 27, 2020, 11:16:50 am »
Hola Boris,
Estoy teniendo problemas para verificar la conexión. Al entrar en la función
Código: [Seleccionar]
while(Stat == 0)
{
   Stat = ResolvLookUp("www.google.com", Ip, RESOLV_OPT_FORCE)
}
el loop nunca termina. Se queda esperando que se resuelva y nunca vuelve.

Luego de algunas pruebas encontré que el problema viene con el último parámetro RESOLV_OPT_FORCE. Cuando llamo a la función sin la macro, la primera vez la función resuelve el hostname en 150ms, lo que parece coherente. Sin embargo, esto no me sirve para mi aplicación ya que solo haría el chequeo la primera vez y luego devolvería siempre OK por la cache.

No encontré documentación sobre la macro en los manuales, puede ser que haya cambiado algo en la función ResolvLookUp?
Aguardo comentarios.
Gracias.

Soporte

  • Global Moderator
  • Experto
  • *****
  • Mensajes: 2160
  • Soporte Técnico
Re:Revisar conexión a internet
« Respuesta #4 : mayo 27, 2020, 21:10:09 pm »
Buenas, estuve verificando, si, tenés razón, la opción "RESOLV_OPT_FORCE" estaba para un uso interno y pensé que funcionaría de otra manera, pero no es muy conveniente utilizarlo de esa forma, por lo que desestimar el ejemplo anterior.

Hay dos formas, la primera es sin actualización de firmware (versión STX8091 < 231), de la siguiente manera:

Código: (Pawn) [Seleccionar]
stock CheckInternetIsOK_MethodTwo()
{
   new Ip
   new Stat
   
   //
   // Resolver nombre y esperar IP.
   //
   
   // Obtener IP de un nombre y llenamos caché.
   while((Stat = ResolvLookUp("www.bing.com", Ip)) == 0)
   {
      // Vacío.
   }
   
   // Forzamos a obtener IP porque caché está lleno con nombre anterior.
   while((Stat = ResolvLookUp("www.google.com", Ip)) == 0)
   {
      // Vacío.
   }
   
   // Comprobar si el nombre pudo ser resuelto.
   if(Stat == 1)
   {
      // Nombre resuelto, hay internet.
      return 1
   }
   else
   {
      // No se pudo resolver nombre, no hay internet.
      return 0
   }
}

La otra forma, requiere actualización de firmware (versión STX8091 >= 231 y StxLadder >= 2.0.8 ), y es mejor para futura compatibilidad (dispositivos con más memoria caché):

Código: (Pawn) [Seleccionar]
stock CheckInternetIsOK()
{
   new Ip
   new Stat
   
   //
   // Resolver nombre y esperar IP.
   //
   
   // Limpiar tablas de caché de nombres, para forzar al "resolver" buscar
   // la IP de un nombre. Esperar en caso que "resolver" esté siendo utilizado
   // por otra aplicación (mail, cliente web, NTP, etc).
   while(ResolvClearCache() < 0)
   {
      // Vacío.
   }
   
   // Obtener IP.
   while((Stat = ResolvLookUp("www.google.com", Ip)) == 0)
   {
      // Vacío.
   }
   
   // Comprobar si el nombre pudo ser resuelto.
   if(Stat == 1)
   {
      // Nombre resuelto, hay internet.
      return 1
   }
   else
   {
      // No se pudo resolver nombre, no hay internet.
      return 0
   }
}

Además es el doble más rápida en caso que no haya internet.

Por si decidís usar la versión con firmware nuevo:

Todavía no está liberado StxLadder 2.0.8, pero te paso el archivo "resolv.inc" que te da acceso a la función nueva ResolvClearCache(), entonces, colócar archivo en el directorio de StxLadder que tengas instalado:

C:\<directorio de instalación>\slicetex\StxLadder\pawn\include\common

(sobrescribir el archivo previo que se encuentre en dicho directorio).

El firmware te lo adjunto a continuación: stx8091-d2-v231.sff

También un proyecto en Pawn de prueba con ambas opciones. Cuando no hay internet, se apaga el Led DEBUG.

Probalo desconectando el cable Ethernet y decime.

Saludos!
« Última Modificación: mayo 27, 2020, 21:24:49 pm por Soporte »
SOPORTE TÉCNICO

Slicetex Electronics
www.slicetex.com

EBD

  • Aprendiz
  • **
  • Mensajes: 36
Re:Revisar conexión a internet
« Respuesta #5 : mayo 28, 2020, 12:46:34 pm »
Hola Boris,
Buenisimo. Ya estuve probando el método sin firmware nuevo y anduvo perfectamente. Por el momento vamos a ir con ese ya que no soy yo el que instala el programa en los PLC y prefiero esperar a que se libere la versión oficial para cambiar al otro método.

Veo que la función ResolvLookUp() la llamas en un loop bloqueante. ¿Cuál es el tiempo máximo que tiene la función ResolvLookUp() para devolver un -1 en caso de que no haya internet? Ya que, si no tiene un tiempo máximo internamente, debo limitar el tiempo en el while para que el PLC pueda atender otras tareas. ¿Cuál es un tiempo adecuado para esta función?

Por el momento el código lo hice de la siguiente forma.
Limitando el tiempo del primer llamado al resolver se redujo el tiempo que tarda en detectar la falta de conectividad (parece que la cache se limpia de todas formas). Sospecho que si el resolver está haciendo otras tareas quizás 2 segundos no es tiempo suficiente. Por favor, recomendame un tiempo adecuado para el primer llamado también.
En el caso del segundo llamado a ResolvLookUp(), noté que tarda alrededor de 15 segundos en devolver -1 cuando no hay internet, aunque esté número varía un poco. Sin embargo, esto es en mi casa y no sé si en otro ambiente con una peor conexión podría tardar más.

Espero por tus comentarios sobre los temas planteados.
Gracias.
Código: [Seleccionar]
CheckInternetIsOk()
{
   new Ip
   new Stat

   // Obtener IP de un nombre y llenamos caché.
   new tempStart = TimeGetMillis()
   while( (ResolvLookUp("www.bing.com", Ip)) == 0 && (TimeGetMillis()-tempStart < 2000)){}
   tempStart = TimeGetMillis()
   while( (Stat = ResolvLookUp("www.google.com", Ip)) == 0 && (TimeGetMillis()-tempStart < 20000)){}
   
   return Stat
}


Soporte

  • Global Moderator
  • Experto
  • *****
  • Mensajes: 2160
  • Soporte Técnico
Re:Revisar conexión a internet
« Respuesta #6 : mayo 28, 2020, 13:19:02 pm »
Buenos días,

Veo que la función ResolvLookUp() la llamas en un loop bloqueante. ¿Cuál es el tiempo máximo que tiene la función ResolvLookUp() para devolver un -1 en caso de que no haya internet? Ya que, si no tiene un tiempo máximo internamente, debo limitar el tiempo en el while para que el PLC pueda atender otras tareas. ¿Cuál es un tiempo adecuado para esta función?

Si, de esa forma planteada es bloqueante, hay que rebuscarlo un poco para que no sea bloqueante, por ejemplo, te recomiendo llamarla cada un segundo a la función reescrita de la siguiente forma:

Código: (Pawn) [Seleccionar]

// Variable global.
new CheckInternetInProgress = 0
new InternetIsUP = 0

// Función
stock CheckInternetIsOK()
{
   new Ip
   new Stat
   
   //
   // Resolver nombre y esperar IP.
   //
   
   // Verificar si hay una comprobación de internet en progreso.
   if(CheckInternetInProgress  == 0)
   {
      // No, obtener IP de un nombre para llenar caché.
      Stat = ResolvLookUp("www.bing.com", Ip)
     
      // Procesar código de retorno.
      if(Stat == 0)
      {
          // Esperando repuesta, retornar.
          return 1
      }
      else if(Stat == 1)
      {
          // Primera dirección IP obtenida, retornar.
          CheckInternetInProgress  = 1
          return 1
      } 
      else
      {
          // No se pudo obtener IP, no hay internet.
          InternetIsUP = 0
          return 0
      }
   }
   else
   {
      // Comprobación de internet en progreso, segunda parte.

      // Forzamos a obtener IP porque caché está lleno con nombre anterior.
      Stat = ResolvLookUp("www.google.com", Ip)
     
      // Procesar código de retorno.
      if(Stat == 0)
      {
          // Esperando repuesta, retornar.
          return 1
      }
      else if(Stat == 1)
      {
          // Segunda dirección IP obtenida, fin de operación, retornar.
          CheckInternetInProgress  = 0
          InternetIsUP = 1
          return 1
      } 
      else
      {
          // No se pudo obtener IP, no hay internet, fin de operación, retornar.
          CheckInternetInProgress  = 0
          InternetIsUP = 0
          return 0
      }
   }
}

No la probé, pero es la idea para que no te bloqueé si la llamás periódicamente. Salvo detalle, debe funcionar.

Retorna "1" mientras exista internet, pero como este valor es "instantáneo" (ya que mientras espera retorna 1), te puse la variable "InternetIsUP", que solo va a ser 1 si hay internet y 0 si no lo hay.

(parece que la cache se limpia de todas formas).

Si, el caché es de una entrada, por lo tanto, si se pidió otro nombre diferente al último, fuerza a buscar. Esto puede cambiar en otros dispositivos o en futuras versiones que asignen más memoria. Por ello, luego lo podés actualizar con ResolvClearCache() para mejor compatibilidad.

En el caso del segundo llamado a ResolvLookUp(), noté que tarda alrededor de 15 segundos en devolver -1 cuando no hay internet, aunque esté número varía un poco. Sin embargo, esto es en mi casa y no sé si en otro ambiente con una peor conexión podría tardar más.

Si, tarda un aproximado de 15 segundos al no encontrar conexión, también depende del servidor, conexión, difícil de medir, pero de la forma no bloqueante que te puse arriba, no tendrías este problema y lo podrías hacer en "segundo plano".

Si no querés estar pidiendo constantemente nombres a internet, podés llamarla cada cierto tiempo de forma intensiva, es decir, cada 15 minutos, la habilitás para que se llame cada 1 segundo. Luego si hay internet, dejás de llamarla y la llamás en 15 minutos nuevamente.

Saludos!
« Última Modificación: mayo 28, 2020, 13:37:29 pm por Soporte »
SOPORTE TÉCNICO

Slicetex Electronics
www.slicetex.com

Soporte

  • Global Moderator
  • Experto
  • *****
  • Mensajes: 2160
  • Soporte Técnico
Re:Revisar conexión a internet
« Respuesta #7 : mayo 28, 2020, 13:39:08 pm »
Nota: Le agregué la variable "InternetIsUP" al código anterior que así es mejor, solo leer esa variable para saber si hay o no hay internet. Ya que la función, luego de retornar "0" (sin internet) en una próxima llamada retorna "1" por un periodo de tiempo breve hasta que nuevamente determina que no hay internet.

Quizás el nombre de la función debería llamarse InternetStatusUpdate() para que se entienda más su finalidad al llamarla periódicamente.
« Última Modificación: mayo 28, 2020, 13:43:31 pm por Soporte »
SOPORTE TÉCNICO

Slicetex Electronics
www.slicetex.com

EBD

  • Aprendiz
  • **
  • Mensajes: 36
Re:Revisar conexión a internet
« Respuesta #8 : mayo 28, 2020, 16:09:01 pm »
Perfecto. Ya lo hice andar de forma no bloqueante y aprovechando que las 2 direcciones son distintas utilizo las 2 para chequear el estado de internet. Te copio el código abajo por si a alguien le resulta útil.

Código: [Seleccionar]
new startTime = 0
new endTime = 0
new bool: InternetIsUP = false
new bool: needMainteinance = true

PlcMain()
{
VirtualHmiInit()
RtcOnSecondSetEvent()  // Crea una interrupción cada 1 segundo para actualizar display
new webOk = 0
for(;;)
{
nLcdPrintf(0, 0, LCD_CLRALL, "---- Internet Tester ----")
if(needMainteinance == true)
{
startTime = TimeGetMillis()
webOk = InternetManteinance()
endTime = TimeGetMillis()
needMainteinance = false
}
if(webOk != -2)
nLcdPrintf(0, 1, LCD_NONE, "Updating internet status...")

nLcdPrintf(0, 2, LCD_NONE, "Manteinance retVal = %d (Delay=%d ms)", webOk, endTime-startTime)
nLcdPrintf(0, 4, LCD_NONE, "INTERNET STATUS = %d", InternetIsUP)
DelayMS(500)
}

return 0
}

#define MAINTENANCE_PERIOD 20 // seconds
// To be called periodically (~every 1 second) (WITHOUT INTERRUPT)
InternetManteinance()
{
static bool: usedMainAdd = false
static lastUpdate = 0
new Stat = -2
if( (TimeGetMillis() - lastUpdate) > MAINTENANCE_PERIOD*1000 )
{
new Ip

if(usedMainAdd == false)
Stat = ResolvLookUp("www.google.com", Ip)
else
Stat = ResolvLookUp("www.bing.com", Ip)


if(Stat != 0) // If resolver finished
{
usedMainAdd = !usedMainAdd
lastUpdate = TimeGetMillis()
InternetIsUP = (Stat == 1 ? true : false)
LedToggle()
}
}
return Stat
}

@OnRtcSecond()
{
needMainteinance = true
}


Soporte

  • Global Moderator
  • Experto
  • *****
  • Mensajes: 2160
  • Soporte Técnico
Re:Revisar conexión a internet
« Respuesta #9 : mayo 28, 2020, 16:20:35 pm »
Muy bien, excelente. Saludos!
SOPORTE TÉCNICO

Slicetex Electronics
www.slicetex.com