Création d'un service d'interrogation HTTP GET sur un client Raspberry Pi

8

J'ai le matériel suivant:

  1. 3 x photons de particules . Chacun sert de serveur HTTP

  2. 1 x Raspberry Pi 3 qui servira de client HTTP

Sur demande d'un HTTP GET à l'un des photons, l'API renvoie:

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

Je veux créer un schéma d'interrogation où le client Raspberry Pi effectue un HTTP GET toutes les 0,1 seconde sur chacun des 3 serveurs.

Je ne sais pas s'il existe quelque chose comme HTTP Polling et si les bibliothèques asynchrones comme Twisted by Python devraient être celles à utiliser.

J'aimerais obtenir des conseils sur la façon dont un modèle à plusieurs serveurs et à client unique fonctionnerait par rapport à HTTP?

Référence

Chaque photon de particules a la réponse JSON mentionnée ci-dessus à une requête HTTP GET.

Le Raspberry Pi servirait de client HTTP, essayant d'obtenir des demandes de chaque photon de particules. image composante avec le Pi et trois photons et direction des appels de repos

Shan-Desai
la source
3
Le Raspberry Pi ne se limite pas à parler à un serveur distant à la fois. Si vous pouvez faire fonctionner un client avec une connexion TCP maintenue en vie, vous pouvez probablement en jongler trois à la fois, soit en utilisant trois copies du programme, trois threads, soit en jonglant avec soin les descripteurs de fichiers dans un seul thread, probablement dans un grande boucle select ().
Chris Stratton
1
Vous pouvez utiliser un navigateur à partir d'un Pi. Chaque onglet est un client, chacun peut accéder à un serveur différent. Où est le problème? Si le navigateur peut le faire, votre code aussi. C'est simple
Mawg dit réintégrer Monica
1
Les questions de codage sont probablement mieux posées sur stackoverflow.com D'autant plus qu'il s'agit d'une pure question HTTP et indépendante de l'appareil
Mawg dit de rétablir Monica

Réponses:

6

J'ai trouvé une bonne solution de base pour ce que @Chris Stratton fait référence à une connexion TCP maintenue en vie:

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"

Vous devez créer une boucle éternelle qui attend 0,1 s, puis effectue l'une de ces étapes entre la connexion et la fermeture afin que la connexion ne soit appelée qu'une seule fois au démarrage et à la fermeture uniquement en cas d'extrême nécessité de tout arrêter.

Avec les fils, une fois que le précédent fonctionne:

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() 

Sources:

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
la source
3

Peut-être que les liens suivants peuvent vous aider:

Exemple de client de base: https://docs.python.org/2/library/asyncore.html#asyncore-example-basic-http-client

Exemple de serveur d'écho de base: https://docs.python.org/2/library/asyncore.html#asyncore-example-basic-echo-server

Avez-vous également pensé à utiliser le protocole UDP? c'est peut-être mieux ...

Et je conseillerais que HTTP / 1.0, pour autant que je sache, n'est pas obligatoire dans son implémentation, pour maintenir les connexions en vie, qui a été défini dans HTTP / 1.1; de toute façon cela dépend de l'implémentation, cela peut avoir ou pas.


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
la source
1
Comment cela aide-t-il les choses? Vous semblez fournir un exemple trivial de l'établissement d'une connexion HTTP à la dure, mais qu'est-ce que cela offre pour résoudre le problème réel de la question - c'est-à-dire, comment cela aide-t-il l'utilisateur à interroger plusieurs appareils?
Chris Stratton