Bienvenue sur IndexError.

Ici vous pouvez poser des questions sur Python et le Framework Django.

Mais aussi sur les technos front comme React, Angular, Typescript et Javascript en général.

Consultez la FAQ pour améliorer vos chances d'avoir des réponses à vos questions.

Bottle + AutobahnPython + pcduino

+4 votes

Je suis en Python3 et souhaite créer un petit site Web avec Bottle sur une pcduino (Ubuntu). Comme j'aurai besoin des websockets (pour mettre à jour la page Web en temps réel à partir des données reçues des capteurs), je compte utiliser AutobahnPython avec twisted.

J'ai donc suivi cela mais il me dit ImportError: No module named 'twisted.web.wsgi'. J'imagine que ce module n'a pas encore été porté.

Du coup, il me reste deux solutions :

  • Lancer mes serveurs HTTP et WS dans deux terminaux différents ;
  • Travailler avec des threads.

J'ignore pour laquelle opter et s'il en existe une troisième, meilleure.

A noter qu'un troisième facteur rentre en jeu : comme pour une Arduino classique, le code Python gérant la pcduino effectuera une boucle infinie.

demandé 23-Jul-2015 par Vayel (1,050 points)
edité 23-Jul-2015 par Vayel

5 Réponses

+3 votes
 
Meilleure réponse

Je commence à comprendre ce qui te pose problème : tu veux pouvoir gérer les handlers http et les handlers websocket dans le même script serveur.

Tu vas donc devoir faire un mix des deux dans le même script.

La partie serveur sera sur, je suppose ton PC de développement ou ta station de travail, c'est cette partie qui fera l'affichage avec le handler http et qui fera la collecte avec le handler websocket.

Ton PCduino sera donc uniquement le client websocket.

Comme je suis sympa ;), je vais te donner un lien qui permet de gérer tout ça avec le même framework.

Donc tu utilises Flask et tu lui adjoints cette bibliothèque tierce :

https://github.com/kennethreitz/flask-sockets

Un exemple :

from flask import Flask
from flask_sockets import Sockets

app = Flask(__name__)
sockets = Sockets(app)

@sockets.route('/echo')
def echo_socket(ws):
    while True:
        message = ws.receive()
        ws.send(message)

@app.route('/')
def hello():
    return 'Hello World!'

Je crois que c'est la solution la plus simple si tu n'as jamais travaillé avec les websockets.

Cela dit, si tu pars sur asyncio, rien ne t'empêche dans le même script de lancer un serveur capable de gérer le http et un serveur chargé de gérer les websockets.

Pour finir, tu as aussi d'autres solutions, à titre personnel, je n'aime pas utiliser les websockets car on se retrouve avec plein de callbacks, je préfère travailler avec des files d'attente de messages dans le genre zeromq et msgpack. Mais je ne sais pas ce qu'est capable de gérer le côté pcduino. Bref il y a plusieurs manière de gérer le truc.

répondu 23-Jul-2015 par DoubleNain (1,662 points)
sélectionné 18-Aou-2015 par Vayel

Non, pcDuino n'est pas un client Websocket mais un serveur. Il collecte des informations via des capteurs et les rend disponibles via une interface Web. Websocket me permet de mettre automatiquement à jour la page pour avoir les valeurs des capteurs en temps réel.

Je pourrais passer par WAMP, mais ça m'embête de démarrer un Crossbar sur ma pcDuino pour un seul client.

Du coup, j'ai trois trucs :

  • La boucle infinie de mon programme Python lisant les valeurs des capteurs ;
  • Un serveur WS ;
  • Un serveur HTTP.

Les deux premiers doivent être ensembles vu que je veux pouvoir pusher des informations à l'app Web suite à la lecture d'un capteur. Intégrer le troisième aux deux précédents me permet de tout démarrer via un seul script, mais ce n'est pas obligatoire.

Pour information, pcDuino est un Ubuntu classique (Lubuntu plus précisément). Je ne dispose que de deux machines : une pcDuino et une tablette Android pour consulter l'app Web.

Du coup, j'ai opté pour cela, mais avec cette lib. Il faut que je regarde laquelle est la mieux.

Concernant la boucle infinie de la pcDuino, une solution est d'utiliser un thread, comme illustré ici. Si tu es d'accord, pourrais-tu éditer ton message afin que la réponse soit complète ?

+2 votes

Comme tu es en Python 3, je te conseille d'utiliser une solution plus légère à base des modules asyncio et websockets. C'est simple, propre et performant. Ici, l'exemple utilise le pattern Producer / Consumer pour illustrer l'échange entre le server et le client.

Un petit exemple d'utilisation :

import asyncio
import websockets

# Server
@asyncio.coroutine
def producer(websocket, uri):
    count = 0
    while websocket.open:
        yield from asyncio.sleep(1)
        count = count + 1
        yield from websocket.send(str(count))

# Client
@asyncio.coroutine
def consumer():
    websocket = yield from websockets.connect('ws://localhost:8765/')
    while websocket.open:
        count = yield from websocket.recv()
        print("%s" % count)

start_server = websockets.serve(producer, 'localhost', 8765)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_until_complete(consumer())
asyncio.get_event_loop().run_forever()

L'exemple a été trouvé sur ce site : http://hautefeuille.eu/asyncio-python.html

Bien sûr, tu peux aussi regarder du côté de Crossbar ou de Api-hour, ou Flask.

Après, sur le même site, tu as la méthode hard avec gevent : http://hautefeuille.eu/websocket-python-et-gevent.html

Mais je ne te conseille pas d'utiliser gevent. Asyncio est plus adapté avec Python 3.

répondu 23-Jul-2015 par DoubleNain (1,662 points)
edité 23-Jul-2015 par DoubleNain

En effet, ça semble plus léger, mais où me faut-il démarrer mon serveur HTTP dans cette histoire ? Parce que je me retrouve avec le même problème que Autobahn.

+2 votes

il y a aussi zmq qui monte en ce moment et qui est asynchrone.
Apparemment en association avec tornado tu pourrais utiliser websocket.

répondu 23-Jul-2015 par buffalo974 (2,608 points)

n'oublies pas de refiler 2-3 liens dans les réponses c'est toujours + cool =D

zmq = zeromq dont le lien est au dessus ;)

l'ionnocent lecteur qui passe par ici pourra pa forcément deviner =P

0 votes
répondu 30-Jul-2015 par DoubleNain (1,662 points)
0 votes

Tu as aussi Pulsar, ça rox pas mal !

https://pypi.python.org/pypi/pulsar

répondu 5-Aou-2015 par DoubleNain (1,662 points)
...