Crear un servicio de sondeo HTTP GET en un cliente Raspberry Pi

8

Tengo el siguiente hardware:

  1. 3 x fotones de partículas . Cada uno sirve como un servidor HTTP

  2. 1 x Raspberry Pi 3 que servirá como un cliente HTTP

Al solicitar un HTTP GET a cualquiera de los Photons, la API devuelve:

{
  node: 1,
  uptime: 1234556,
  location: 'back',
  sensor: {
      Eu: {// Euler Angles from IMU
           h: 0, p: 0, r: 0
      },
      La: {// linear Acceleration values from IMU
           x: 0, y: 0, z: 0
      }
  }
}

Quiero crear un esquema de sondeo donde el cliente Raspberry Pi realiza un HTTP GET cada 0.1 segundo en cada uno de los 3 servidores.

No estoy seguro de si hay algo como sondeo HTTP y si las bibliotecas asincrónicas como Twisted by Python deberían ser las que se utilizarán.

Me gustaría obtener algunos consejos sobre cómo funcionaría un modelo de Servidor múltiple - Cliente único wrt HTTP.

Referencia

Cada Particle Photon tiene la respuesta JSON mencionada anteriormente a una solicitud HTTP GET.

La Raspberry Pi serviría como un Cliente HTTP, tratando de obtener solicitudes de todos y cada uno de los Fotones de Partículas. imagen componente con Pi y tres fotones y dirección de llamadas de descanso

Shan-Desai
fuente
3
El raspberry pi no se limita a hablar con un servidor remoto a la vez. Si puede hacer que un cliente funcione con una conexión TCP mantenida viva, presumiblemente puede hacer malabarismos con tres a la vez, ya sea usando tres copias del programa, tres hilos o haciendo malabarismos con los descriptores de archivos con cuidado en un solo hilo, probablemente en un bucle grande select ().
Chris Stratton
1
Puede usar un navegador desde un Pi. Cada pestaña es un cliente, cada uno puede acceder a un servidor diferente. ¿Dónde está el problema? Si el navegador puede hacerlo, también puede hacerlo su código. Es sencillo
Mawg dice que reinstale a Mónica el
1
Las preguntas de codificación probablemente se hagan mejor en stackoverflow.com Especialmente porque esta es una pregunta HTTP pura e independiente del dispositivo
Mawg dice que reinstalar a Monica el

Respuestas:

6

Encontré una buena solución base para lo que @Chris Stratton se refiere a una conexión tcp mantenida viva:

import socket

# Set up a TCP/IP socket
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

# Connect as client to a selected server
# on a specified port
s.connect(("url_to_device_n",80))

# Protocol exchange - sends and receives
s.send("GET /answer_json HTTP/1.0\n\n")
while True:
    resp = s.recv(1024)
    if resp == "": break
    print resp, # here instead of print parse json

# Close the connection when completed
s.close()
print "\ndone"

Debe hacer un bucle eterno que espere 0.1s y luego realice uno de estos pasos entre conectar y cerrar para que se llame a conectar solo una vez al inicio y se cierre solo cuando sea extremadamente necesario apagar todo.

Con hilos, una vez que los trabajos anteriores:

import urllib2 
from multiprocessing.dummy import Pool as ThreadPool 
import socket
import time

def sendData( urlToDevice ):
   # Set up a TCP/IP socket
   s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
   s.connect(("url_to_device_n",80))
   while True:
      time.sleep(0.1)
      # Protocol exchange - sends and receives
      s.send("GET /answer_json HTTP/1.0\n\n")
      while True:
         resp = s.recv(1024)
         if resp == "": break
         print resp, # here instead of print parse json

    # Close the connection when completed
    s.close()
    print "\ndone"

#########################   
# This is main program: #
#########################

urls = [
      'url_to_device_1', 
      'url_to_device_2',
      'url_to_device_3',
      '..',
      'url_to_device_n',
      ]

# make the Pool of workers
pool = ThreadPool(n) 

# open the urls in their own threads
results = pool.map(sendData, urls)

# close the pool and wait for the work to finish 
pool.close() 
pool.join() 

Fuentes:

http://www.wellho.net/resources/ex.php4?item=y303/browser.py

/programming/2846653/how-to-use-threading-in-python

/programming/510348/how-can-i-make-a-time-delay-in-python

mico
fuente
3

Tal vez los siguientes enlaces pueden ayudarlo:

Ejemplo de cliente básico: https://docs.python.org/2/library/asyncore.html#asyncore-example-basic-http-client

Ejemplo de servidor de eco básico: https://docs.python.org/2/library/asyncore.html#asyncore-example-basic-echo-server

Además, ¿has pensado en usar el protocolo UDP? puede ser mejor ...

Y recomendaría que HTTP / 1.0, hasta donde yo sé, no sea obligatorio en su implementación, para mantener las conexiones activas, que se definió en HTTP / 1.1; de todos modos depende de la implementación, puede tener o no.


import asyncore, socket

class HTTPClient(asyncore.dispatcher):

    def __init__(self, host, path):
        asyncore.dispatcher.__init__(self)
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.connect( (host, 80) )
        self.buffer = 'GET %s HTTP/1.0\r\n\r\n' % path

    def handle_connect(self):
        pass

    def handle_close(self):
        self.close()

    def handle_read(self):
        print self.recv(8192)

    def writable(self):
        return (len(self.buffer) > 0)

    def handle_write(self):
        sent = self.send(self.buffer)
        self.buffer = self.buffer[sent:]


client = HTTPClient('www.python.org', '/')
asyncore.loop()

import asyncore
import socket

class EchoHandler(asyncore.dispatcher_with_send):

    def handle_read(self):
        data = self.recv(8192)
        if data:
            self.send(data)

class EchoServer(asyncore.dispatcher):

    def __init__(self, host, port):
        asyncore.dispatcher.__init__(self)
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.set_reuse_addr()
        self.bind((host, port))
        self.listen(5)

    def handle_accept(self):
        pair = self.accept()
        if pair is not None:
            sock, addr = pair
            print 'Incoming connection from %s' % repr(addr)
            handler = EchoHandler(sock)

server = EchoServer('localhost', 8080)
asyncore.loop()
sergio gonzalez collado
fuente
1
¿Cómo ayuda esto a las cosas? Parece que está proporcionando un ejemplo trivial de hacer una conexión HTTP de la manera difícil, pero ¿qué ofrece eso para resolver el problema real de la pregunta, es decir, cómo ayuda esto al usuario a sondear múltiples dispositivos?
Chris Stratton