Criando um serviço de pesquisa HTTP GET em um Raspberry Pi Client

8

Eu tenho o seguinte hardware:

  1. 3 x fótons de partículas . Cada um serve como um servidor HTTP

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

Ao solicitar um HTTP GET para qualquer um dos fótons, a API retorna:

{
  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
      }
  }
}

Desejo criar um esquema de pesquisa em que o cliente Raspberry Pi executa um HTTP GET a cada 0,1 segundo em cada um dos três servidores.

Não tenho certeza se existe algo como HTTP Polling e se as Bibliotecas assíncronas como Twisted by Python devem ser as únicas a serem usadas.

Gostaria de obter alguns conselhos sobre como um modelo de Servidor Múltiplo - Servidor Único funcionaria em HTTP errado?

Referência

Cada fóton de partículas tem a resposta JSON mencionada acima para uma solicitação HTTP GET.

O Raspberry Pi serviria como um cliente HTTP, tentando obter solicitações de todos os fótons de partículas. imagem componente com o Pi e três fótons e direção das chamadas de repouso

Shan-Desai
fonte
3
O raspberry pi não se limita a conversar com um servidor remoto por vez. Se você pode fazer um cliente funcionar com uma conexão TCP mantida ativa, presumivelmente você pode manipular três de uma vez, usando três cópias do programa, três threads ou manipulando os descritores de arquivo com cuidado em um único thread, provavelmente em um grande laço select ().
22817 Chris Stratton
1
Você pode usar um navegador de um Pi. Cada guia é um cliente, cada um pode acessar um servidor diferente. Onde está o problema? Se o navegador conseguir, o seu código também. É simples
Mawg diz restabelecer Monica 08/08/17
1
As perguntas sobre codificação provavelmente são mais bem colocadas no stackoverflow.com Especialmente porque essa é uma questão HTTP pura e independente de dispositivo
Mawg diz que restabelece Monica em

Respostas:

6

Encontrei uma boa solução básica para o que @Chris Stratton se refere a uma conexão tcp mantida 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"

Você deve fazer um loop eterno que aguarde 0,1s e, em seguida, execute uma dessas etapas entre conectar e fechar, para que a conexão seja chamada apenas uma vez no início e feche somente quando houver extrema necessidade de desligar tudo.

Com threads, uma vez que os trabalhos 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() 

Fontes:

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
fonte
3

Talvez os seguintes links possam ajudá-lo:

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

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

Além disso, você já pensou em usar o protocolo UDP? pode ser melhor ...

E eu aconselho sobre o HTTP / 1.0, tanto quanto sei, não é obrigatório em sua implementação, para manter as conexões ativas, definidas no HTTP / 1.1; de qualquer maneira, depende da implementação, pode ter ou não pode.


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
fonte
1
Como isso ajuda as coisas? Você parece estar fornecendo um exemplo trivial de fazer uma conexão HTTP da maneira mais difícil, mas o que isso oferece para solucionar o problema real da pergunta - ou seja, como isso ajuda o usuário a pesquisar vários dispositivos?
Chris Stratton