Problèmes pour un réseau de machines à café

Le problème exposé dans ce sujet a été résolu.

Bonjour à tous,

Je ne sais pas si je poste dans la catégorie du forum adaptée mais mon problème englobe plusieurs domaines informatiques. Je suis en train de réaliser une interface pour une cafetière connectée et j'hésite entre plusieurs solutions techniques. Je requiers vos conseils et avis :) .

Mon projet se découpe en trois parties : une interface de commande qui consiste en un site WEB, un "transmetteur" qui transmet les ordres de l'interface à la cafetière, et la cafetière connectée à Internet qui répond à certaines requêtes en produisant le café et en retournant un code de réponse.

L'interface permet à l'utilisateur de commander son café depuis son ordinateur (lancer la production d'une tasse). Elle prend la forme d'un site WEB qui utilise PHP. Le "transmetteur" a pour rôle de relayer les ordres de l'interface à la cafetière : c'est un programme réseau (fait avec Qt) auquel on indique une adresse et un port et qui se charge d'envoyer la requête appropriée à la machine à café.

Mon souci concerne la communication entre l'interface et le "transmetteur". J'ai pour cela plusieurs solutions :

  • utiliser une base de donnée qui s'interpose entre l'interface WEB et le "transmetteur". Ce dernier lit en permanence les dernières entrées d'une table "commandes" (sur laquelle viennent s'ajouter les commandes des utilisateurs) et transmet en conséquence à la cafetière,
  • lancer une instance du "transmetteur" depuis mon script PHP à chaque soumission de commande. Le "transmetteur" envoie alors la requête appropriée à la cafetière.

Or :

  • dans le premier cas on surcharge la base de donnée de requêtes (ce qui est mauvais, non ?),
  • dans le second cas, j'aimerais savoir si l'on peut émettre plusieurs requêtes TCP (et attendre leur réponse) en même temps car le temps de traitement de la requête par la cafetière peut prendre plusieurs secondes.

Je précise que mon projet repose sur le fait que le système de commandes est centralisé autour d'un serveur. Je ne souhaite pas que le cafetière fournisse elle-même l'interface WEB. Cela me permettra d'ajouter à l'avenir de nouvelles cafetières au réseau.

Quelle solution préférez-vous ?

J'espère que mon message est clair, sinon demandez-moi ;) .

Croal

+0 -0

Comment tes cafetières sont-elles connectées au réseau ?
Elles communiquent en HTCPCP ?

Je ne comprend pas bien ta question sinon. Bien-sûr qu'on peut émettre plusieurs requêtes en même temps. Mais pas sur le même port (port chez toi), mais ça ne devrait pas être une limitation.

PS: Ton titre est pas du tout explicite.

+0 -0

Salut Ache,

Pour l'instant mes cafetières utilisent Arduino et un module Ethernet pour leur accès réseau. Un port est ouvert dans chacun de leurs réseaux pour qu'elle puisse recevoir les requêtes du transmetteur. J'utilise effectivement le HTCPCP pour l'instant mais je compte réécrire un protocole à partir de celui-ci car il ne correspond pas bien à mes attentes.

En fait j'ai besoin d'émettre différentes requêtes vers différentes machines. Sauf que je ne peux pas me permettre d'attendre les réponses (qui peuvent prendre plusieurs secondes) entre chaque envoi. Il se peut aussi que les propriétaires des machines choisissent d'utiliser le même port. Donc je ne sais pas trop comment remédier à ce problème.

Pour le titre, je vais régler ça.

Alors du coup il n'y a pas de problème.

Par exemple, si tu veux communiquer avec un équipement disons la cafetière paul sur le port 1337. Tu vas communiquer avec paul:1337.

Ton ordi va choisir un port disons 62544. Il va envoyer un paquet sur le port 1337 de la machine paul. Donc personne ne peut communiquer avec paul sur le même port. Mais toi tu peux communiquer avec marie sur le port 1337 sans problème, il suffit de choisir un autre port que 62544 par exemple au pif 31415.

Résultat, tu peux communiquer avec paull:1337 et marie:1337 en même temps ! :D

Dis moi si je suis complètement à coté …

+1 -0

Merci pour tes précieuses réponses ;) ! Donc la librairie réseau de Qt ne met pas en pause mon programme après l'envoi d'une requête TCP ?

Sinon il me reste juste une chose à savoir et j’opterai pour la première solution : une base de donnée telle que MySQL peut-elle supporter plusieurs centaines de requêtes par seconde ?

Donc tu utilises des sockets.

Supposons que tu envoies un paquet à une cafetière (car j'aime beaucoup l'idée). Tu as 2 manières d'attendre la réponse. Soit tu l'attends, soit toutes les Xms tu vérifies si tu as bien reçu une réponse ou pas. Tu peux également ne pas avoir besoin de la réponse et donc cette étape n'est pas obligatoire mais dans le protocole HTCPCP tu doit attendre la réponse.

La première est bloquante, la deuxième ne l'est pas.

Une solution pour pouvoir attendre une réponse de manière bloquante (plus rapide, plus simple) sans bloquer l'application est d'utiliser un fils d’exécution différent. Un Thread en somme, Qt propose ça je crois certainement par QThread.

Pour le SQL, je ne sais pas trop, je ne m'y connais pas beaucoup, mais se baser sur un modèle où on demande 100 requêtes par seconde à un serveur SQL me semble bancale.

MySQL de ce que j'en sais est surtout utilisé pour des applications avec peu de besoin en performance.

+0 -0

Je vais essayer de me renseigner sur les Threads. Sinon je pensais qu'utiliser un signal lorsque l'on reçoit des données (le SIGNAL(readyRead()) ), ne suspendait pas le programme ?

Pour le SQL, je vais peut-être opter pour la seconde solution : ainsi la BDD ne sera pas surchargée de requêtes qui ne retournerons pas de nouvelles commandes.

Je te tiens au courant de l'avancement :p et voici la maquette de l'interface :

Capture d'écran de l'interface Coffee Network

+0 -0

Je ne comprend pas l'intérêt d'avoir une machine à café sur internet…

Si j'ai envie d'un café la machine ne sera pas trop loin de moi pourquoi aurai-je besoin d'un pc/téléphone avec une connexion internet alors qu'il me suffit d'appuyer sur un bouton sur la machine ?

+0 -0

Bonjour,

Je viens rajouter mon petit grain de sel dans ce débat fort intéressant. J'ai un projet un peu prêt similaire et personnellement j'ai fait le choix d'utiliser MQTT. C'est un protocole développé pour les objets connectés qui a quelques avantage :

  • Super léger

  • Pas besoin de base de donnée

  • Tu pourras lui envoyer des ordres ordres depuis n'importe quel client MQTT standard (dispo sur Android, Linux, Windows, …)

  • Très facile à implémenter sur une Raspberry PI (peut être aussi sur Arduino).

En résumé :

Ta cafetière se connecte à un broker et s'abonne à tes commandes, ainsi quand ton broker va recevoir une commande il va réveiller ta cafetière et lui transmettre ses commandes.

+0 -0

Pour ajouter a ce que dit cbouree : si le but est d'apprendre mieux vaut utiliser des solutions réellement adaptées et pensées pour. Si par exemple tu choisis MQTT, c'est l'occasion d'apprendre a penser et structurer ton projet autour du pattern de PUB/SUB, et tu as pour cela le choix entre les diverses solutions disponibles (il y en a pour a peu prés tous les langages et plateformes, notamment arduino).

Utiliser une base de données (au sens large) pour le suivi de commandes peut être une bonne idée, mais tout dépend de tes besoins. Le but serait non pas de faire un polling dessus pour connaitre les nouvelles commandes (c'est probablement inutile), mais de pouvoir centraliser la gestion des commandes indépendamment des clients (dans le cas contraire, seule la connexion client -> cafetière te permet de faire le lien entre la commande et le café, ce qui n'est pas judicieux).

Note bien que l'usage d'une base de données n'est absolument pas contradictoire avec l'approche PUB/SUB. C'est juste que l'acteur intermédiaire qui va gérer les commandes (disons le contrôleur) pourrait utiliser une base de données pour ce faire, si nécessaire. [Il existe même des bases de données qui supportent nativement le PUB/SUB, comme redis.]

Salut,

Perso je ne comprends pas trop l'utilité d'un logiciel en QT puisque tu dis que les clients commandent via un site web en PHP. Pourquoi PHP ne se connecte pas directement à la cafetière ?

Ca ne t'empêcherais pas d'ajouter/enlever des machines dynamiquement, ou d'en choisir une aléatoirement parmi les disponibles au temps T par exemple. C'est ici qu'une petite base de donnée peut éventuellement être utile.

Le logiciel QT me paraît d'autant plus inutile que ta cafetière utilise un protocole basé sur HTTP, ou plus généralement un protocole texte via TCP. J'aurais éventuellement compris si tu communiquais via USB, série, RS232, etc. car PHP ne peut pas le faire nativement de manière simple, mais là…

L'idée est assez amusante en tout cas !

+0 -0

Tout d'abord je ne connaissais pas le protocole MQTT et il semble parfaitement convenir à mon projet : je vais me renseigner dessus et je vous tiens au courant.

En réponse au message de Yoch : j'aimerais justement centraliser la gestion des commandes. Ainsi il y aurait diverses interfaces de commande (site WEB, client bureau, application Android, etc.) qui enverraient les ordres de l'utilisateur à un serveur central qui les stock dans une BDD et qui se charge de transformer la demande en requête HTCPCP et l'envoie à la machine à café. S'agit-il d'une architecture PUB/SUB ? Mon problème à l'origine de ce sujet c'est que le contrôleur du serveur (qui gère l'envoie des requêtes HTCPCP) est obligé de consulter régulièrement une BDD pour savoir si de nouvelles commandes sont à transmettre. MQTT me permettrait-il d'avoir une solution plus "élégante" ?

Pour QuentinC : en fait j'ai besoin qu'un élément logiciel du serveur central construise la requête à destination de la cafetière et c'est pour cela que j'utilise Qt car, à ma connaissance, PHP ne permet pas d'envoyer arbitrairement et nativement des requêtes TCP à destination d'une autre machine que celle qui est à l'origine de son lancement. Non ?

En tout cas, merci pour vos réponses qui m'aide beaucoup :) !

à ma connaissance, PHP ne permet pas d'envoyer arbitrairement et nativement des requêtes TCP à destination d'une autre machine que celle qui est à l'origine de son lancement. Non ?

Bien sûr que si. Voir fsockopen ou sockets A condition bien sûr que tu contrôles le serveur web et le php.ini (car les hébergeurs normaux bloquent évidemment souvent cette possibilité).

+0 -0

En réponse au message de Yoch : j'aimerais justement centraliser la gestion des commandes. Ainsi il y aurait diverses interfaces de commande (site WEB, client bureau, application Android, etc.) qui enverraient les ordres de l'utilisateur à un serveur central qui les stock dans une BDD et qui se charge de transformer la demande en requête HTCPCP et l'envoie à la machine à café. S'agit-il d'une architecture PUB/SUB ?

Pas particulièrement, c'est une architecture client / serveur assez classique, sauf que tu as ici deux type de serveurs et de clients :

  1. tu as le serveur de commande, auquel se connectent les différentes UIs (clients) ;
  2. chaque cafetière (il y en a plusieurs ?) joue aussi le rôle de serveur, et a cette étape ton serveur central joue le rôle de client.

Mon problème à l'origine de ce sujet c'est que le contrôleur du serveur (qui gère l'envoie des requêtes HTCPCP) est obligé de consulter régulièrement une BDD pour savoir si de nouvelles commandes sont à transmettre.

Je ne vois pas bien pourquoi il devrait faire ce genre de polling: au moment ou tu enregistre la commande dans ta DB, tu peux envoyer directement la requête a la cafetière qui va bien.

MQTT me permettrait-il d'avoir une solution plus "élégante" ?

D'un certain point de vue, oui. Avec une architecture PUB/SUB (mais cela va bien sur dépendre de la façon dont tu l'organise, et c'est selon moi le point le plus intéressant ici), tu peux « passer une commande » en laissant un numéro de commande, par exemple, et être contacté lorsque le café est prêt. Un peu comme si tu définissais un callback, mais a distance.

En ultra simplifié (pas de serveur central, une seule cafetière), ça pourrait donner quelque chose comme ça :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
+---------+              +----------+           +-----------+
|         |              |          |           |           |
|  client |              |  broker  |           |  cafeti.  |
|         |              |          |           |           |
+----+----+              +-----+----+           +------+----+
     |                         |                       |
     |                         |      SUB(cmd/+)       |
     |                         <-----------------------+
     |       SUB(rcpt/x)       |                       |
     +------------------------->                       |
     |                         |                       |
     |                         |                       |
     |    PUB(cmd/x, my_cmd)   |                       |
     +------------------------->                       |
     |                         |   PUB(cmd/x, my_cmd)  |
     |                         +----------------------->
     |                         |                       |
     |                         |                       |
     |                         |  PUB(rcpt/x, coffee)  |
     |                         <-----------------------+
     |    PUB(rcpt/x, coffee)  |                       |
     <-------------------------+                       |
     |                         |                       |
     v                         v                       v

A retenir tout de même que l'un des avantages principaux de MQTT (mis a part sa légèreté qui en fait un protocole de choix pour l'embarqué) et du PUB/SUB en général est le découplage fort qu'il introduit: les composants du système n'ont pas besoin de se connaitre entre eux.

Et ceci a un prix : tu ne peux pas savoir si une cafetière est connectée au moment ou tu passe une commande, il te faut prévoir toi même la façon d'assigner chaque commande a une cafetière en particulier (par exemple en utilisant un topic différent pour chaque cafetière), etc.

D'autres approches comme l'emploi de files de messages permettent de résoudre le problème un peu différemment, mais toujours dans le même esprit de communication par messages. Et bien évidement, tu peux aussi résoudre ton problème avec une architecture plus classique.

@QuentinC : je ne connaissais pas cette fonctionnalité ! J'y penserais à l'avenir.

En ce qui concerne la BDD, je pensais faire du polling pour communiquer la commande de l'interface Web (avec le script PHP) à mon transmetteur Qt. En effet je ne savais pas jusqu'à alors que je pouvais émettre ma requête directement à partir du PHP.

Je pense effectivement que je vais adopter un système de commande avec numéro comme tu me le suggère. Cependant, dans ton architecture, il faut que les ports du LAN client soient ouverts pour qu'il puisse recevoir la réponse à son premier PUB, non ?

Je pense effectivement que je vais adopter un système de commande avec numéro comme tu me le suggère.

Attention, mon architecture reste un "jouet".

Si tu veux en savoir un peu plus sur MQTT, les MQTT Essentials de HiveMQ sont très bien faits. Tu peux aussi explorer d'autres solutions, comme par exemple le protocole wamp, ou les solutions basées sur des files de messages (queues).

Cependant, dans ton architecture, il faut que les ports du LAN client soient ouverts pour qu'il puisse recevoir la réponse à son premier PUB, non ?

En MQTT, seul le broker doit tourner sur une machine accessible de l’extérieur, les clients maintiennent la connexion tout le temps donc pas de souci de ce cote. Il suffit donc juste d'indiquer aux clients l'adresse du broker, d'une façon ou d'une autre.

+0 -0

Je viens encore dans le but d'essayer de complexifier ton projet, mais uniquement dans le but que tu en soit encore plus fière hein ;)

Pourquoi PHP, PHP est tout sauf une solution d'avenir…

Avec NodeJS tu implémentes MQTT avec une facilité déconcertante. Sans parler de la meilleur rapidité de NodeJS (qui à aucun intérêt dans ton cas). Mais surtout avec NodeJS tu pourras :

  • Avec l’utilisation de Socket.io forcer le rafraichissement de tous tes clients web connectés en temps réel sans être obligé de flood ton serveur avec de l'Ajax ou similaire. (Bien plus simple à utiliser que de l'Ajax)

  • Créer ton propre Broker : c'est lui qui s'occupera de mettre à jour la base de donnée pour les informations que tu veux persistantes. Et de ce fait tu pourras utiliser n'importe quel client MQTT standard pour communiquer avec ta cafetière (ET TA BDD) et ce sans avoir besoin que ton serveur web tourne. Il ne faut pas que ça te fasse peur car le code minimal d'un broker est d'une 20taine de lignes.

En soit ce n'est pas obligatoire pour que ton projet fonctionne bien (et de manière plutôt propre tout de même), mais personnellement j'y ai vu là l’occasion d'essayer NodeJS. Je ne regrette pas.

PS: J'ai quasiment fini un projet similaire si jamais tu es vraiment perdu je peux t'ajouter au dépôt, MP moi ;)

+0 -0

C'est un peu un discours marketing que tu nous fais la… (PHP vs Node.js, toussa).

Il ne faut pas que ça te fasse peur car le code minimal d'un broker est d'une 20taine de lignes.

Probablement pas d'un broker MQTT en tout cas. Ou alors je ne demande qu'a voir.

Implémenter un broker MQTT n'est clairement pas si simple, encore moins si on cherche la performance, ou on veut implémenter le protocole complet. Ça me parait largement hors scope et sans intérêt particulier pour ce type de projet (de ce que j'ai compris, le but n'est pas de réinventer la roue, même si c'est surement instructif par ailleurs).

Je ne parle pas de tout réécrire… Mais plutôt d'en recréer une version simple

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
var mosca = require('mosca')

var ascoltatore = {
  //using ascoltatore
  type: 'mongo',
  url: 'mongodb://localhost:27017/mqtt',
  pubsubCollection: 'ascoltatori',
  mongo: {}
};

var settings = {
  port: 1883,
  backend: ascoltatore
};

server.on('clientConnected', function(client) {
    console.log('client connected', client.id);
});

// fired when a message is received
server.on('published', function(packet, client) {
  console.log('Published', packet.payload);
  if ((packet.topic.indexOf('tables/') > -1)) {
     //Traitement de toutes les publications des tables (tables/*)
  }
});

var server = new mosca.Server(settings);
server.on('ready', setup);

// fired when the mqtt server is ready
function setup() {
  console.log('Mosca server is up and running')
}

Et oui c'est un discourt un peu marketing, mais tu avoueras que tu ne peux pas implémenter un broker avec si peu de ligne en PHP ?

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte