Sign inSign up

jusaba/ngrokserverpic

By jusaba

Updated over 2 years ago

ngrok para cámara ESP32 en Serverpic

Image
Internet of things
0

1.9K

jusaba/ngrokserverpic repository overview

Video en Serverpic con ngrok

Esta imagen ha sido creada para proporcionar a Serverpic la posibilidad de recibir video de camaras con ESP32. ngrok*, como se define en su web, es una API que agrega conectividad a las aplicaciones. Ngrok crea túneles para hacer visibles los servidores de una LAN en internet.

El contenedor, soportado en Python 3, contiene ngrok y pyngrok. Pyngrok es una librería que permite la gestión de ngrok desde python.

En el contenedor se ejecuta una pequeña aplicación en python de forma que se crea un usuario más de Serverpic que atenderá las peticiones de otros clientes, normalmente cámaras, para crear el túnel que les de visibilidad en internet.

La petición de video se realizará desde un cliente Web de Serverpic. El protocolo de interconexion entre Web, Camara y Cliente Python es el siguiente

WEBCAMARAPython
mensaje-:-CAMARA-:-CamaraOn
Procesa CamaraOn
mensaje-:-python-:-WEB-:-Ip
Procesa texto '-:-'
Crea tunel ngrok a Ip
Inicio temporizacion tunel
mensaje-:-CAMARA-:-Sitio-:-WEB-:-http sitio ngrok
Procesa texto 'Sitio-:-'
mensaje-:-WEB-:-Sitio-:-http sitio ngrok
Suscripcion Sitio
Abre ventana video a http ngrok
.
(Temporiza tiempo de video)
.
mensaje-:-CAMARA-:-CamaraOff
Procesa texto 'CamaraOff'
mensaje-:-Python-:-SitioOff
Suscripcion SitioOffProcesa texto 'SitioOff'
Cierra ventana videoPasa a estado Espera
Instalación 🔧

Para descargar la imagen

docker push jusaba/ngrokserverpic:latest
Pre-requisitos 📋

_ La carpeta en la que se compile el Dockerfile debe contener el programa Serverpic.py que gestiona ngrpk

#TCPclient.py
#!/usr/bin/python
import sys
import socket
import time
import sys, http.client, urllib
#import commands
import os, time

from pyngrok.conf import PyngrokConfig
from pyngrok import ngrok, conf



def CreaTunelCamara (s, cIp, cRemitente, cDestinatario, cId):
    ngrok.set_auth_token(cId)
    camara_tunnel = ngrok.connect(cIp+':81', 'tcp')
    #obtenemos el sitio asignado por ngrok
    tunnels = ngrok.get_tunnels()
    cSitio = tunnels[0].public_url
    nPosIni = cSitio.find("tcp")
    cSitio = ("http:"+cSitio[nPosIni+4:]+'/stream')

    print(cSitio)
    print('mensaje-:-'+cRemitente+'-:-Sitio-:-'+cDestinatario+'-:-'+cSitio)
    time.sleep(1)
    s.send(("mensaje-:-"+cRemitente+"-:-Sitio-:-"+cDestinatario+"-:-"+cSitio).encode())
    s.send(b"\n")
    ngrok_process = ngrok.get_ngrok_process()
    time.sleep(15)
    s.send(("mensaje-:-"+cRemitente+"-:-CamaraOff").encode())
    s.send(b"\n")
    ngrok.kill()

    try:
        # Block until CTRL-C or some other terminating event
        ngrok_process.proc.wait()
    except KeyboardInterrupt:
        print(" Shutting down server.")
        ngrok.kill()

def ConexionServidor ( Servidor, Puerto, NombreCliente ):
        data=str()
        lSalida = 0
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s = socket.socket()
        s.connect( (Servidor, Puerto) )
        s.send(data.encode())
        data = s.recv(256)
        if  data.decode() == "CONECTADO\n" :
            print ("Conectado a servidor")
            s.send(NombreCliente.encode())
            s.send(b"\n")
            data = s.recv(256)
            if data.decode() == "Registrado\n" :
                print ("Registrado en servidor")
                lSalida = 1
        s.setblocking(0)
        return lSalida, s

def Latido (s):
    lSalida = 0
    s.setblocking(1)
    s.send(b"Latido")
    s.send(b"\n")
    data = oSocket.recv(256)
    if data.decode() == "Ok\n" :
       lSalida = 1
    print ("datos: " + data.decode())
    print ("Latido")
    print (lSalida)
    s.setblocking(0)
    return lSalida

data=str()
lConexion = 0
lPing = 0
Estado = 0
nPos = 0
nTemp = 0
nLatidos = 0

while True:                                                                                           
    try:                                                                                              
        if Estado == 0:                                                                               
            lConexion,oSocket=ConexionServidor (sys.argv[1], int(sys.argv[2]), sys.argv[3] )          
            if lConexion == 1  :                                                                      
                Estado = 1                                                                            
                print ("Conexion Ok")                                                                 
        if Estado == 1:                                                                               
            nTemp = nTemp+1                                                                           
            #print ("Esperando en Estado 1....")                                                      
            if nTemp == 1000000 :                                                                          
                nTemp = 0
                if Latido(oSocket) == 0 :
                    nNoLatido = nNoLatido + 1
                else :
                    nNoLatido = 0
                if nNoLatido == 2 :
                    oSocket.close
                    time.sleep (1)
                    Estado = 0            
            data = oSocket.recv(256)                                                                  
            print ("datos: " + data.decode())                                                         
            nPos =  (data.decode()).find("-:-")                                                       
            if nPos > -1 :                                                                            
                aDatos = (data.decode()).split("-:-")                                                 
                cIp = aDatos[2]                                                                       
                ch = '\n'                                                                             
                cIp = cIp.rstrip(ch)                                                                  
                cDestinatario = aDatos[1]                                                             
                cRemitente = aDatos[0]                                                                
                CreaTunelCamara (oSocket, cIp, cRemitente, cDestinatario, sys.argv[4] )               
                Estado = 2                                                                            
        if Estado == 2:                                                                               
            #print ("Esperando para cerrar....")                                                      
            nTemp = nTemp + 1                                                                         
            if nTemp == 1000000 :                                                                          
                nTemp = 0                                                                             
                if Latido(oSocket) == 0 :
                    nNoLatido = nNoLatido + 1
                else :
                    nNoLatido = 0
                    nLatidos = nLatidos + 1                                                               
                    if nLatidos == 2 :                                                                    
                        nLatidos = 0                                                                      
                        Estado = 1                                                                        
                        print ("cambio forzado a estado 1 ")   
            if nNoLatido == 2 :
                    oSocket.close
                    time.sleep (1)
                    Estado = 0        
            else:            
                data = oSocket.recv(256)                                                                  
                print ("datos: " + data.decode())                                                         
                nPos =  (data.decode()).find("SitioOff")                                                  
                if nPos > -1 :                                                                            
                   Estado = 1                                                                            
        if Estado == 3:                                                
            oSocket.close                                              
            sys.exit(1)                                                
            nPos=0                                                     
    except socket.error as  e:
        if (e.errno) != 11 :
                # si no es excepcion de setblocking (11)
                print(e)
                time.sleep(2)
        try:
            oSocket.close
        except NameError:
            # = None
            print ("Error: No hay conexion con el servidor ")

#sys.exit(1)
oSocket.close
                                                              

El comando para ejecutar Serverpic.py es el siguiente

python Serverpic.py ${Mundo} ${Puerto} ${Usuario} ${Token}

Donde:

Mundo.- Mundo al que se va a conectar el cliente python
Puerto.- Puerto correspondiente al mundo seleccionado
Usuario.- Nombre del cliente python que se va a conectar a Serverpic
Token.- Token de ngrok. Dato proporcionado al crear una cuenta ngrok

Ejecutando lai magen ⚙️

Para poner en marcha el contenedor

docker run -e Mundo=mundo.jusaba.es -e Puerto=9000 -e Usuario=Video -e Token=2Tp...GG9 --name ngrok -d jusaba/ngrokserverpic:latest

Donde los parametros empleados corresponden con los detallados en el apartado de Serverpic.py

Si se desea entrar en el contenedor en ejecución

docker exec -it ngrok bash

Como se ha construido la imagen 🛠️

La imagen se ha creado mediante el siguiente Dockerfile

FROM python:3

ENV TZ=Europe/Madrid

LABEL version=1.0
LABEL autor=Julian_Salas


RUN apt-get update --allow-unauthenticated -y
RUN apt-get upgrade --allow-unauthenticated -y

RUN apt-get install wget -y
RUN apt install curl -y
RUN apt-get install nano

RUN  curl -s https://ngrok-agent.s3.amazonaws.com/ngrok.asc | tee /etc/apt/trusted.gpg.d/ngrok.asc >/dev/null && echo "deb https://ngrok-agent.s3.amazonaws.com buster main" | tee /etc/apt/sources.list.d/ngrok.list && apt update && apt install ngrok
RUN pip install pyinstaller
RUN pip install pyngrok


WORKDIR /home/pi/ngrok
VOLUME /home/pi/ngrok/data

COPY ./Serverpic.py /home/pi/ngrok/Serverpic.py

CMD python Serverpic.py ${Mundo} ${Puerto} ${Usuario} ${Token}

La imagen esta creada sobre Python 3, en primer lugar se actualiza el sistema, luego se instala wget y curl para poder descargar los paquetes ngrok y pynegrok. Se crea el directorio de trabajo donde se deja el programa Serverpic.py

El Dockerfile lo ejecutamos como es costumbre

docker buildx build --platform=linux/amd64,linux/arm64,linux/arm/v7 -t jusaba/ngrokserverpic:latest . --push

Para el desarrollo no es necesario crear la imagen para todas las plataformas, para el desarrollo desde windows se ha utilizado el comando

docker buildx build --platform=linux/amd64 -t jusaba/ngrokserverpic:latest . --push

Contribuyendo 🖇️

Wiki 📖

Versionado 📌

Usamos SemVer para el versionado. Para todas las versiones disponibles, mira los tags en este repositorio.

Autores ✒️

  • Oscar Salas Mestres Diseño de Dockerfile
  • Julián Salas Barolome Diseño Serverpic.py, implantación en Serverpic y creación de la documentación

Licencia 📄

Este proyecto es libre para utilizarlo en Serverpic

Expresiones de Gratitud 🎁

  • Comenta a otros sobre este proyecto 📢
  • Invita una cerveza 🍺 o un café ☕ a alguien del equipo.
  • Da las gracias públicamente 🤓.
  • etc.

⌨️ La presentación de esta documentación ha sido posible gracias a Villanuevand 😊

Tag summary

Content type

Image

Digest

sha256:af906aa7e

Size

395.1 MB

Last updated

over 2 years ago

docker pull jusaba/ngrokserverpic