Il est conseillé de lire ou de s’aider de ce document et de ses cours réseaux avant de poursuive.
Le panneau lumineux est un afficheur extérieur à Leds 16x96 (Ambre, pitch 16). Il a été facturé 2550 euros HT par la société DVI SIGNS.
Site : www.dvisigns.com
Les documentations sur ce panneau lumineux sont ici : doc/panneau-lumineux/
Lire le document sur l'installation du panneau lumineux et ses outils.
Vous devez avoir noté son adresse MAC pour continuer.
Lire le document sur l’installation de l’afficheur lumineux LED Moving Sign.
Le panneau lumineux possède une liaison Ethernet via un module LTRX XPort de Lantronix. Ce module réalise un pont RS232-RS485/Ethernet.
Ici, l'adresse MAC du module LTRX XPort du panneau lumineux est 00:20:4A:BA:01:C7.
Pour cette partie, vous allez avoir besoin d'un analyseur de protocoles.
Lancer wireshark en mode root.
$ gksudo wireshark &
Ou :
Vérifier si l’adresse MAC du panneau est présente dans votre cache ARP :
$ arp -v
Address HWtype HWaddress Flags Mask Iface
Démarrer une capture wireshark sur votre interface réseau et filtrer les trames qui contiennent seulement l’adresse MAC du panneau :
Ici, l'adresse IP du panneau est 192.168.52.250.
Remarque : il est aussi possible d’activer un ping
en broadcast avec l’option -b
.
Si vous devez modifier cette adresse : consulter le document Assigner une adresse IP au panneau lumineux.
$ ping -c 1 192.168.52.250
PING 192.168.52.250 (192.168.52.250) 56(84) bytes of data.
64 bytes from 192.168.52.250: icmp_req=1 ttl=64 time=0.399 ms
--- 192.168.52.250 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.399/0.399/0.399/0.000 ms
$ nmap -A -T4 192.168.52.250
Starting Nmap 5.21 ( http://nmap.org ) at 2015-11-20 16:05 CET
Nmap scan report for 192.168.52.250
Host is up (0.0044s latency).
Not shown: 996 closed ports
PORT STATE SERVICE VERSION
80/tcp open http Lantronix XPort embedded ethernet http config
|_html-title: Site doesn't have a title (text/html).
9999/tcp open telnet Lantronix XPort telnetd 6.6.0.2 080926 (MAC 00204ABA01C7)
10001/tcp open unknown
30718/tcp open unknown
Service detection performed. Please report any incorrect results at http://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 43.78 seconds
Il y a 4 ports ouverts, le panneau lumineux exécute donc 4 serveurs :
http
) sur le port 80 pour la configurationtelnet
sur le port 9999 pour la configurationIci, le port de communication TCP à joindre est 10001.
Pour cette partie, vous allez avoir besoin d'un analyseur de protocoles.
Vérifier si wireshark est installé, sinon installez le.
Lien : www.wireshark.org/download.html
La communication avec le panneau lumineux repose sur un protocole constructeur MovingSign. Le protocole MovingSign intervient au niveau la couche Application du modèle DoD et utilise les protocoles TCP et IP pour les couches Transport et Réseau. Les échanges avec l’afficheur se feront donc via un client TCP.
Vous devez avoir identifié l'adresse IP et le numero de port du panneau lumineux avant de continuer.
On se limitera à l’étude de deux types de trames :
Les trames de commandes de contrôle sont utilisées pour modifier les paramètres du panneau (luminosité, horodatage, etc …) et pour l’initialiser après chaque allumage.
Exécuter le logiciel Multimedia led 2007.
Démarrer une capture wireshark sur votre interface réseau et filtrer les trames qui contiennent seulement l’adresse IP de votre panneau :
Documentations : doc/panneau-lumineux/
Exemples de résultat attendu :
Diagramme d’échange
Modification de la luminosité
La trame d’initialisation
etc …
Qt fournit un module QtNetwork
qu’il faut activer dans son fichier de projet .pro
pour pouvoir accéder aux classes :
...
QT += network
...
Pour inclure les déclarations des classes de ce module, il vous faut utiliser la directive suivante :
#include <QtNetwork>
Dans ce module, Qt fournit de nombreuses classes pour rendre la programmation réseau simple et portable :
En résumé, on disposera :
QFtp
pour les protocoles de la couche ApplicationQTcpSocket
, QTcpServer
et QUdpSocket
QNetworkConfiguration
, QNetworkConfigurationManager
, …Remarque : La classe QTcpSocket
fournit une interface pour le protocole TCP. On peut donc utiliser QTcpSocket
pour implémenter des protocoles réseau standard comme POP et SMTP, aussi bien que des protocoles personnalisés ou propriétaire.
Apparu dans les systèmes UNIX, un socket est un élément logiciel qui est aujourd’hui répandu dans la plupart des systèmes d’exploitation. Il s’agit d’une interface de communication logicielle avec les services du système d’exploitation, grâce à laquelle un développeur exploitera facilement et de manière uniforme les services d’un protocole réseau. Il s’agit d’un modèle permettant la communication bidirectionnelle inter processus IPC (Inter Process Communication) afin de permettre à divers processus de communiquer aussi bien sur une même machine qu’à travers un réseau TCP/IP. Les sockets se situent entre la couche Transport et la couche Application. En résumé, une socket est un point de communication par lequel un processus peut émettre et recevoir des informations. Ce point de communication devra être relié à une adresse IP et un numéro de port et associé à un mode de communication, le plus souvent : le mode connecté (TCP) ou le mode non connecté (UDP).
Ici, nous allons avoir besoin de la classe QTcpSocket
pour réaliser un client TCP :
La classe QTcpSocket
est asynchrone et émet des signaux pour reporter des changements de statuts et des erreurs. Elle repose sur une boucle d’événements pour détecter des données arrivantes et automatiquement envoyer les données partantes.
Les signaux qu’il faut au minimum gérer par connect()
côté client sont :
readyRead()
signale que des données ont été reçues et sont prêtes à être luesbytesWritten()
signale que des données ont été écritesconnected()
signale que la socket est dans l’état connectédisconnected()
signale que la socket est dans l’état déconnectéerror()
signale qu’une erreur s’est produite sur la socketVous pouvez écrire des données dans le socket avec QTcpSocket::write()
et en lire avec QTcpSocket::read()
.
Remarque : QTcpSocket
possède deux flux indépendants de données : un pour écrire et l’autre pour lire.
Il est possible d’attendre que des données aient été écrites (avec waitForBytesWritten()
) ou reçues (avec waitForReadyRead()
). En lisant depuis un QTcpSocket
, vous devez être sûr qu’assez de données sont disponibles en appelant QTcpSocket::bytesAvailable()
avant.
On appellera la méthode non bloquante QTcpSocket::connectToHost()
pour se connecter à un serveur. Une connexion TCP doit être établie vers un hôte distant et un port avant que le transfert de données puisse commencer. Une fois la connexion établie, l’adresse IP et le port du point de communication distant sont disponibles avec les fonctions QTcpSocket::peerAddress()
et QTcpSocket::peerPort()
. À n’importe quel moment, le point de communication distant peut fermer la connexion et le transfert de données s’arrêtera immédiatement.
On se déconnecte du serveur en appelant disconnectFromHost()
.
Remarque : Qt fournit la classe QHostAddress
pour manipuler des adresses IP.
Le principe de communication d’un client TCP est le suivant :
#include <QtNetwork>
#include "movingsign.h" // le protocole MovingSign
#define TIMEOUT_READ 2000
#define TIMEOUT_WRITE 100
QTcpSocket* socket; // un pointeur sur un QTcpSocket
// instancie la classe QTcpSocket
socket = new QTcpSocket;
// signaux/slots à faire
//connect(socket, SIGNAL(connected()),this, SLOT(connected()));
//connect(socket, SIGNAL(disconnected()),this, SLOT(disconnected()));
//connect(socket, SIGNAL(bytesWritten(qint64)),this, SLOT(bytesWritten(qint64)));
//connect(socket, SIGNAL(readyRead()),this, SLOT(readyRead()));
// connexion
socket->connectToHost(QHostAddress("192.168.52.250"), 10001, QTcpSocket::ReadWrite);
if( (socket->state() == QTcpSocket::ConnectedState) || (socket->waitForConnected(100) == true) )
{
qDebug() << "Connexion ok";
}
else
{
qDebug() << "Connexion impossible !";
}
// préparation de la trame à envoyer
QByteArray trame; // une trame
trame += NUL;
trame += NUL;
trame += NUL;
trame += NUL;
trame += NUL;
trame += SOH;
trame += SENDER_ADDRESS;
// ... cf. protocole MovingSign
// envoi de la trame
socket->write(trame);
// attente envoi
if(socket->waitForBytesWritten(TIMEOUT_WRITE) == true)
{
// données reçues ?
if(socket->waitForReadyRead(TIMEOUT_READ) == true)
{
int octetsRecus = socket->bytesAvailable();
qDebug() << "Nb octets reçus : " << socket->bytesAvailable();
QByteArray donneesRecues = socket->readAll();
qDebug() << "Données reçues : " << donneesRecues;
}
else
{
qDebug() << "Aucune donnée reçue ! " << socket->errorString();
}
}
else
{
qDebug() << "Aucune donnée envoyée ! " << socket->errorString();
}
// déconnexion
socket->disconnectFromHost();
if( (socket->state() == QTcpSocket::UnconnectedState) || (socket->waitForDisconnected(100) == true) )
{
qDebug() << "Déconnexion ok";
}
else
{
qDebug() << "Déconnexion impossible !";
}
delete socket;
Pour faire simple ici, le protocole MovinSign se définira à base de constantes :
const char NUL = 0x00;
const char SOH = 0x01;
const char STX = 0x02;
const char ETX = 0x03;
const char EOT = 0x04;
const QString SENDER_ADDRESS = "FF";
// ...
Objectif : Être capable d’afficher un message sur le panneau lumineux via le réseau.
Code source fourni : activite-commande-panneau.zip
On vous fournit une classe PanneauLumineux
que vous devez compléter et mettre en oeuvre. Pour cela, vous complèterez l’application GUI fournie qui permettra de saisir un message et l’envoyer au panneau lumineux. On pourra paramétrer la communication en saisissant l’adresse IP et le numéro de port du serveur embarqué de l’afficheur. L’application intègrera deux boutons pour se connecter ou se déconnecter.
Remarque : le panneau lumineux stocke dans sa mémoire le dernier message reçu et affiché. À chaque mise sous tension, le panneau réaffichera ce message. Il est intéressant d’avoir la possibilité de réinitialiser un message vierge.
L’application doit pouvoir gérer les erreurs de connexion :
Et d’envoi de message :
Par la suite, vous intégrerez la possibilité de modifier quelques paramètres d’affichage (le type, la vitesse, l’alignement, la taille de la police, …) à partir de l’IHM.