IMA4 2016/2017 P44
Sommaire
Cahier des charges
Présentation générale du projet
L'idée générale de ce projet est de donner une seconde vie aux minitels en les transformant en terminaux d'accès internet.
Contexte
Le Minitel (Médium interactif par numérisation d'information téléphonique) est un type de terminal informatique qui était destiné à la connexion au service français de Vidéotex baptisé Télétel. Lancé en 1980 en France, il permettait d’accéder à de nombreux services (annuaire, jeux, vente par correspondance, tchat ...) à une époque où peu de foyers possédaient un ordinateur. Le service a été arrêté en 2012, les minitels sont maintenant inutilisables et ne servent donc plus à rien, c'est pourquoi il peut être intéressant de leur donner une seconde vie afin d'éviter le gaspillage.
Objectif du projet
L'objectif du projet est d'adapter intégralement le site internet Facebook.com à l'affichage sur minitel. L'utilisateur doit pouvoir surfer sur son minitel de la façon la plus ergonomique possible.
Description du projet
Les minitels disposent généralement d'une prise série appelée prise péri-informatique permettant de communiquer avec le monde extérieur. En connectant une plateforme micro-contrôleur à cette prise série, on peut réaliser l'accès à des pages web et les afficher à l'écran. En raison de la petite taille d'affichage des minitels (24 lignes de 40 ou 80 caractères), il est nécessaire de mettre en place un proxy intermédiaire pour adapter les pages web à l'écran du minitel avant de lui les renvoyer pour affichage.
Choix techniques : matériel et logiciel
- Un Minitel 1 Bistandard Alcatel Telic (permet d'afficher 24 lignes de 80 caractères à l'écran et la transmission par voie série jusqu'à 4800 bauds)<br\>
- Un connecteur DIN 5 broches.
- Une plateforme micro-contrôleur Arduino Uno.
- Une extension Ethernet pour plateforme Arduino.
Calendrier prévisionnel
Pour le bon déroulement du projet, nous avons commencé par étudier les différentes étapes clés de notre projet afin de les planifier.
Liste des tâches à effectuer
- Communication avec le minitel et gestion de l'affichage
Communiquer avec le minitel via la prise série et afficher du texte à l'écran.
Créer une interface ergonomique pour naviguer sur les différentes pages.
- Implémentation du proxy
Visualiser la partie texte seule des pages de Facebook.com à l'aide d'un navigateur adapté afin de réfléchir à comment adapter l'affichage.
Réaliser le proxy intermédiaire pour adapter les pages web à l'affichage du minitel.
- Programmation de la carte Ethernet
Piloter la carte Ethernet avec l'Arduino pour créer un client web.
Calendrier
Feuille d'heures
Tâche | Prélude | Heures S1 | Heures S2 | Heures S3 | Heures S4 | Heures S5 | Heures S6 | Heures S7 | Heures S8 | Heures S9 | Heures S10 | Travail supplémentaire | Total |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Définition cahier des charges | 2 | 2 | |||||||||||
Rédaction du wiki | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 3 | 13 | |
Lecture de la documentation du minitel | 1 | 1 | 1 | 1 | 4 | ||||||||
Recherches, appropriation du matériel | 6 | 4 | 10 | ||||||||||
Fabrication du câble | 2 | 2 | |||||||||||
Codage du programme pour établir la communication série entre l'arduino et le minitel | 4 | 2 | 6 | ||||||||||
Navigation sur Facebook en mode texte | 4 | 4 | |||||||||||
Programmation de l'interface graphique du 3615 Facebook | 5 | 5 | 5 | 5 | 3 | 23 | |||||||
Pilotage de l'ethernet shield et programmation d'un client web sur arduino | 2 | 2 | 2 | 2 | 4 | 4 | 4 | 2 | 22 | ||||
Création du proxy d'adaptation des pages de Facebook | 4 | 6 | 6 | 5 | 4 | 25 | |||||||
Rédaction du rapport | 8 | 8 | |||||||||||
Tournage de la vidéo | 4 | 4 | |||||||||||
Total | 123 |
Avancement du Projet
Semaine 1
Cette première semaine a été consacrée au rassemblement du matériel nécessaire et à sa prise en main, ainsi qu'a des recherches sur internet.
Recherches
Nous avons tout d'abord axé nos recherches sur les différentes façons de communiquer avec le minitel via la plateforme microcontrôleur. La plupart des projets visant a réutiliser le minitel pour diverses applications, utilisent la prise série de celui-ci pour communiquer. Voici différents projets réutilisant un minitel :
- Minitel en terminal série
- Minitel en moniteur télé
- Projet minitel revival
- Minitel et Raspberry pi
- Minitel en terminal linux USB
Nous avons donc étudiés ces différents projets ainsi que la documentation technique du minitel pour comprendre son fonctionnement.
Prise en main du minitel
Le minitel que nous avons à notre disposition est bistandard, c'est à dire qu'il dispose de deux standards :
- Un standard Télétel comprenant deux modes :
- Un mode Vidéotex qui est le mode actif à la mise sous tension du minitel
- Un mode mixte
- Un standard téléinformatique
Nous allons utiliser le mode mixte car il permet d’utiliser l'écran en mode 80 colonnes de caractères (au lieu de 40 en mode Vidéotex), des échanges bidirectionnels simultanés quand le minitel est relié à un autre appareil via sa prise péri-informatique et l'utilisation des commandes protocole permettant par exemple de modifier la vitesse des échanges avec le périphérique en envoyant une commande spécifique avec le périphérique via la prise.
Les commandes intéressantes pour configurer notre minitel sont les suivantes :
Tâche | Commande clavier | Commande par la prise (Hexadécimal) |
---|---|---|
Passage au standard téléinformatique | Fnct + T puis F | 1B 3A 31 7D |
Passage du mode Vidéotex au mode mixte | Indisponible | 1B 3A 32 7D |
Passage de l'écran en mode page/rouleau | Fnct + E puis P / Fnct + E puis R | 1B 3A 6A 43 / 1B 3A 69 43 |
Modifier la vitesse de la prise (1200 bauds par défaut) |
Fnct + P puis 3 pour 300 bauds <br\> Fnct + P puis 1 pour 1200 bauds <br\> Fnct + P puis 4 pour 4800 bauds |
1B 3A 6B 52 <br\> 1B 3A 6B 64 <br\> 1B 3A 6B 76 |
Semaine 2
Recherches
Cette seconde semaine nous avons axé nos recherche l'alimentation de notre plateforme microcontrôleur. La plateforme Arduino embarque un régulateur 12V ce qui nous permet de l'alimenter directement via les broches du minitel.
Fabrication du câble pour connecter le minitel et l'arduino
Lors de cette semaine, nous avons fabriqué le câble qui servira à la communication entre l'arduino et le minitel. Pour cela, nous avons acheté un connecteur DIN 5 broches sur lequel nous avons soudé 5 fils d'un vieux câble ethernet. Après avoir refermé le connecteur, nous avons dénudé les fils à l'autre extrémité afin de pouvoir les relier aux bonnes broches de l'arduino.
Correspondance fils/broches :
Numéro de la broche | Fonction | Couleur du fil |
---|---|---|
1 | Entrée RX | Bleu |
2 | 0V | Vert |
3 | Sortie TX | Orange |
4 | Entrée PT | Marron |
5 | Sortie 8,5V 1A | Blanc |
Semaine 3
Communication série entre le minitel et l'arduino
Ayant réalisé le câble permettant de connecter la prise péri-informatique du minitel à l'arduino, nous avons essayé d'envoyer des caractères au minitel via la liaison série et de les visualiser à l'écran correctement.
D'après le manuel "Minitel 1 B Spécifications techniques d'utilisation" dont le lien est disponible dans le cahier des charges, les niveaux électriques de la prise du minitel sont compatibles avec le niveau TTL, collecteur ouvert :
- Un niveau de tension supérieur ou égal à 2,5 V présenté sur l'entrée RX sera interprété comme un "1" logique
- Un niveau de tension inférieur ou égal à 0,4 V présenté sur l'entrée RX sera interprété comme un "0" logique.
Le format des signaux RX et TX de réception et d'émission du minitel est fixe avec 7 bits de données plus un bit de parité paire.
Nous avons donc codé en C un programme pour l'arduino qui envoie en continu le caractère "a" sur le port série afin de s'assurer de la bonne communication avec le minitel . On utilise la bibliothèque avr/io.h de façon à écrire dans les registres de l'atmega 328 de l'arduino. Le code du programme est donné ci-dessous :
#include <avr/io.h> // For the serial port #define CPU_FREQ 16000000L // Assume a CPU frequency of 16Mhz void init_serial(int speed) //initialisation de la liaison série { /* Set baud rate */ UBRR0 = CPU_FREQ/(((unsigned long int)speed)<<4)-1; /* Enable transmitter & receiver */ UCSR0B = (1<<TXEN0 | 1<<RXEN0); /* Set 7 bits character and 1 stop bit even parity */ UCSR0C = (2<<UPM00)|(2<<UCSZ00); /* Set off UART baud doubler */ UCSR0A &= ~(1 << U2X0); } void send_serial(unsigned char c) //envoyer un carctère sur le port série { loop_until_bit_is_set(UCSR0A, UDRE0); UDR0 = c; } unsigned char get_serial(void) //récupérer un caractère envoyé sur le port série { loop_until_bit_is_set(UCSR0A, RXC0); return UDR0; } int main () { init_serial(1200); while(1) { send_serial('a'); } return 0; }
Semaine 4
Afin de voir à quoi ressemble facebook en mode texte, nous avons installé le navigateur web Links pour linux qui n'affiche que le texte des pages web. La version pour ordinateur de facebook nécessite JavaScript, elle ne peut donc pas fonctionner correctement sur ce type de navigateur. On utilise par conséquent la version mobile de facebook (http://m.facebook.com) plus simple et donc plus adaptée pour un affichage rudimentaire (affichage très limité du minitel). On remarque que faute de pouvoir afficher les images, le navigateur affiche une description de celles-ci.
Programmation de la plateforme Ethernet Shield
La première étape était de pouvoir communiquer avec notre plateforme Ethernet Shield. Pour cela nous avions tout d'abord pensé a connecter la plateforme sur le réseau Polytech mais cela est compliqué et peu pratique pour travailler à l'extérieur. Nous avons donc préféré créer un réseau local entre notre pc et la plateforme. On peut voir ci-dessous le schéma de notre réseau.
Nous avons créé une interface Ethernet sur le pc pour attribuer une ip fixe qui permettra de nous situer sur le même réseau local que la plateforme. Nous avons aussi modifié la table de routage, afin que notre interface soit connectée à internet.
Pour tester le bon fonctionnement de notre réseau, nous avons attribué une adresse MAC et IP via l'IDE Arduino.
Semaine 5
Programmation de l'interface graphique du 3615 Facebook
Nous utilisons le minitel en mode mixte de façon à pouvoir utiliser les commandes protocole (passage en mode mixte, réglage de la vitesse de la prise en 4800 bauds, blocage de l'écran) et l'affichage en 80 colonnes de caractères à l'écran (voir semaine 1). Dans ce mode, peu d'attributs de visualisation des caractères sont disponibles, mais cela suffit pour faire une interface ergonomique. Les attributs disponibles sont donnés dans le tableau ci-dessous ainsi que le code à envoyer au minitel avant les caractères auxquels on veut appliquer l'attribut.
Attributs de visualisation des caractères
Attribut | Code (Hexadécimal) |
---|---|
Aucun | 1B 5B 30 30 6D |
Surintensité / Intensité normale | 1B 5B 30 31 6D / 1B 5B 32 32 6D |
Souligné / Non souligné | 1B 5B 30 34 6D / 1B 5B 32 34 6D |
Clignotant / Non clignotant | 1B 5B 30 35 6D / 1B 5B 32 35 6D |
Fond inversé / Fond normal | 1B 5B 30 37 6D / 1B 5B 32 37 6D |
Des fonction de mise en page sont aussi disponibles en mode mixte, elles nous permettent à tout moment d'agir sur la position du curseur de façon à pouvoir positionner du texte à différents endroits sur l'écran. Ces fonctions avec le code correspondant sont données dans le tableau ci-dessous.
Fonctions de mise en page
Fonction | Code (Hexadécimal) |
---|---|
Déplacement du curseur d'une colonne vers la gauche | 08 |
Déplacement du curseur de 8 colonnes vers la droite | 09 |
Déplacement du curseur d'une ligne vers le bas | 0A |
Retour du curseur en position 1 de la ligne courante | 0D |
Effacer l'écran | 1B 5B 32 4A |
Mettre le curseur en première ligne, première colonne | 1B 5B 00 3B 00 48 |
Bloquer l'affichage sur l'écran / Débloquer | 1B 3B 60 58 50 / 1B 3B 61 58 50 |
Organisation modulaire du code
Notre programme arduino en C comporte 4 fichiers .c et les .h correspondant ainsi que que le fichier main.c et un Makefile.
- arduino.c contient les fonctions de configuration et d'utilisation de la liaison série de l'arduino.
- minitel.c contient les fonctions de configuration du minitel.
- affichage.c contient les fonctions gérant l'affichage à l'écran de l'interface graphique du 3615 facebook.
- connexion.c contient les fonctions relatives à la configuration et à l'utilisation de l’Ethernet Shield.
- main.c contient la fontion main gérant l'exécution du programme d'affichage.
Semaine 6
Programmation de l'interface graphique du 3615 Facebook (suite)
Le minitel ne comportant ni souris, ni écran tactile, il est nécessaire de créer une interface qui se commande uniquement au clavier. L'ergonomie est donc un critère capital sur un terminal de ce type ayant, de plus, un affichage plutôt limité. Pour concevoir l'interface, nous nous sommes inspirés des pages minitel de l'époque qui utilisaient les touches de fonction (Sommaire, Annulation, Retour, Guide, Envoi ...) pour naviguer dans les différents menus. Une touche sera représentée à l'écran en noir sur fond blanc à coté du nom du menu correspondant. Les champs seront représentés par des "underscore" (Recherche : ____________________). Un prototype de la page "fil d'actualité" de Facebook sur minitel est donné ci-dessous.
Problème mémoire avec l'arduino uno
Lors du codage de l'application sur l'arduino, nous avons constaté un problème avec les chaînes de caractères. En effet, le programme compile correctement, mais les dernières chaines de caractères de notre programme ne s'affichent pas correctement sur le minitel. Cela est dû au fait que les chaines de caractères sont stockées dans la mémoire SRAM de l'arduino et que cette mémoire ne peut contenir que 2048 octets. Nous avons cependant besoin de stocker beaucoup de chaines de caractères dans l'arduino. Une solution existe à ce problème, il est possible de stocker les chaines de caractères dans la mémoire flash de l'arduino (mémoire de programme) qui peut contenir 32 Ko.
Pour stocker une chaîne de caractères dans la mémoire flash, on utilise l'attribut PROGMEM de la bibliothèque avr/pgmspace.h :
static const char chaine[] PROGMEM = "Chaine de caracteres";
Pour lire les chaîne de caractères stockées dans la mémoire flash et les envoyer sur le port série pour l'affichage sur l'écran du minitel, on utilise la fonction suivante :
void afficher_flash(const char chaine[]) { int k; char myChar; int len = strlen_P(chaine); for (k = 0; k < len; k++) { myChar = pgm_read_byte_near(chaine + k); send_serial(myChar); } }
https://www.arduino.cc/en/tutorial/memory
Programmation de la plateforme Ethernet Shield (suite)
La puce wiznet W5100 permet de communiquer avec notre microcontrôleur via un bus SPI. Il se comporte comme un esclave, le maître vient lire et écrire dans les différents registres de l'esclave. Elle permet la gestion des piles TCP/IP (Datasheet W5100). Avant de programmer notre plateforme en client, nous avons tout d'abord voulu correctement programmer notre interface en nous inspirant de ce projet.
Semaine 7
Caractères affichables sur le minitel
Le minitel dispose deux jeux de caractère :
- Un jeu américain
- Un jeu français
L'utilisation des deux jeux de caractère est nécessaire car le caractère '@' est dans le jeu américain et les caractères accentués sont dans le jeu français. La configuration du clavier en jeu français ou américain se fait en envoyant l'octet 0x0E ou 0x0F. Le clavier sera configuré en jeu américain sur la page de connexion pour pouvoir taper l'arobase de l'adresse mail et en jeu français sur toutes les autres pages.
Programmation de la plateforme Ethernet Shield (suite)
La programmation de l'Ethernet Shield via les différents registres nous a posé quelques problèmes, la plateforme était parfois présente sur notre réseau, mais parfois non. Nous avons décidés d'utiliser les librairies fournies par notre tuteur qui permettent directement la programmation de la puce W5100 via des fonction spécifiques:
- W5100.h : décrit les différentes valeurs de registres du W5100 et les fonctions associées.
- Ethernet.h : déclare les paramètres et contient les fonctions d'initialisation de l’ethernet shield.
- Socket.h : contient les différentes fonctions relatives à la gestion des sockets.
- Spi.h : déclare les différentes valeurs relatives à la communication SPI.
Semaine 8
Création d'un proxy pour adapter les pages de Facebook à l'affichage sur minitel
L'arduino uno ne comportant que très peu de mémoire vive (2 ko), il est difficile de se connecter, de récupérer et de stocker directement les pages Facebook avec l'ethernet shield installé sur celui-ci. En effet, les pages html de Facebook comportent beaucoup trop de caractères dont la grande majorité sert à l’esthétique du site. Par exemple, la page de connexion pour appareils mobiles https://m.facebook.com/ comporte plus de 20 000 caractères, et cela est pire sur la version pour ordinateur qui comporte en plus du JavaScript. Nous n'avons de plus besoin que du texte brut des pages pour afficher sur notre minitel, d'où la nécessité de le filtrer. Pour cela, on met en place un serveur web http Apache 2 qui va héberger notre proxy intermédiaire sur lequel l'arduino va se connecter. On installe aussi PHP ainsi que son extension cURL qui permet de récupérer le texte des pages web et de le stocker dans une chaîne de caractères avant de le modifier à l'aide des fonctions de gestion et de manipulation des chaînes de PHP ( http://php.net/manual/fr/ref.strings.php) et de le réafficher sur la nouvelle page.
Programmation de la plateforme Ethernet Shield (suite)
Notre plateforme va se comporter comme un client web, c'est a dire qu'elle va tout d'abord initier une connexion avec notre serveur pour ensuite envoyer des requêtes pour récupérer les informations voulues.
Semaine 9
Connexion à un compte Facebook directement depuis le serveur Apache
Pour pouvoir entrer l'adresse e-mail ainsi que le mot de passe de connexion à un compte Facebook directement depuis le minitel, il faut trouver une méthode permettant de remplir automatiquement les champs correspondants du formulaire PHP de la page "connexion" de Facebook. Nous avons tout d'abord essayé de nous connecter en créant une page avec un formulaire comportant les champs e-mail et mot de passe et qui envoie ces données à la page de connexion à facebook via la méthode POST. Cependant, Facebook détecte les tentatives de connexion venant d'une page extérieure au site et empêche la connexion (voir figure 10). Nous avons donc du trouver un moyen de contourner la sécurité de facebook. Pour cela, nous avons utilisé les fonctions cURL de PHP.
Filtrage du texte des pages Facebook récupérées via les fonctions cURL
Une fois qu'on a récupéré la page d’accueil de facebook connectée sur un compte avec cURL dans une variable $p, on découpe le texte utile de la page avec les fonctions de traitement des chaînes de caractères de PHP. Pour cela, on commence par repérer les balises <p></p>, <a</a>, ou encore les balises <h3</h3>, <h5</h5> qui contiennent du texte. On utilise la commande strip_tags qui permet de supprimer des balises html.
$p=strip_tags($p, '<a>'); supprime toutes les balises html sauf <a</a>
Ainsi, cela permet de se débarrasser des nombreuses balises qui ne contiennent pas de texte à afficher telles que <div>, <span>... On se sert ensuite des balises restantes pour placer des caractères de séparation qui permettent de délimiter les différentes lignes de texte, les différents posts... On utilise la commande strstr qui permet de remplacer toutes les occurrences d'une chaîne de caractères dans la page.
$trans=array("<p>" => "<p>|"); $p=strtr($p, $trans); ici on remplace <p> par <p>| ce qui revient à ajouter le caractère | après chaque balise <p>
Une fois qu'on a placé tous les caractères de séparation dans le texte, on enlève toutes les balises qui restent dans le texte :
$p=strip_tags($p);
Ainsi, il ne reste que les caractères de séparation et le texte des balises. Les caractères de séparation sont interprétés par le minitel de différentes manières et ne seront pas affichés sur son écran. Ils permettent de gérer la mise en page du texte récupéré de façon à l'aérer et qu'il ne soit pas en un seul bloc. Les caractères de séparation introduits dans le texte récupéré par le proxy et leur signification pour le minitel sont donnés dans le tableau ci-dessous :
Caractère de séparation | Signification pour le minitel |
---|---|
@ | Début de texte |
| | Retour à la ligne |
% | Saut de ligne (double retour à la ligne) |
{ | Inversion du fond (texte noir sur fond blanc) jusqu'au prochain retour à la ligne |
} | Fin de texte |
On utilise aussi d'autres fonctions telles que strpos qui permet de trouver la position de la première occurrence d'une chaîne de caractères dans un texte ou strstr qui fait de même mais retourne le texte à partir de la première occurrence de la chaîne au lieu de retourner sa position. substr retourne un segment de chaîne et substr_replace remplace un segment dans une chaîne. Enfin echo affiche une chaîne de caractères.
$p=strpos($p,"Accueil"); retourne la position de la première occurence de la chaîne "Accueil" dans $p $p=strstr($p,"Accueil"); retourne le texte à partir de la première occurrence de la chaîne "Accueil" dans $p $p=substr($p,5,25); retourne la chaîne $p entre les caractères 5 et 25 $p=substr_replace($p,"@",5); remplace le caractère 5 par '@' dans $p echo $p; affiche la chaîne $p
Semaine 10
Implémentations des fonctions du client web
Nous avons commencé à implémenter, les différentes fonctions permettant a notre client de fonctionner. La fonction init_connexion permet d'initialiser la plateforme Ethernet et retourne un socket s. Tout d'abord elle assigne au Wiznet une adresse IP, une adresse mac, la passerelle, et le masque de sous réseau via la fonction ethernet_init() (ethernet.h). Ensuite elle initialise un socket via la fonction socket(), en lui passant en paramètres le socket à initialiser, le protocole de communication souhaité : ici Sn_MR_TCP pour une communication TCP, le port utilisé, et le mode. Elle teste si le socket est correctement initialisé et retourne ce dernier si c'est le cas.
La fonction serveur_connexion est utilisée afin de se connecter au serveur, elle prend en paramètre un socket et renvoie 0 si la connexion est établie et 1 sinon.
La fonction envoi_requete permet l'envoi et la réception de paquets http. Elle prend en paramètre les buffers d'envoi et de réception et le socket de dialogue. Elle retourne la taille des paquets reçus.
La fonction connection_active permet de vérifier si la connexion est active ou non, elle prend en paramètre le socket de dialogue et retourne 0 lorsque la connexion est fermée.
Travail supplémentaire
Nous avons eu besoin de semaines supplémentaires afin d'achever notre projet. Lors des dernières semaines, nous avons testé l'implémentation des différentes parties du programme. Nous avons rencontrés quelques difficultés que nous avons du surmonter :
- Un problème avec le buffer de réception qui ne se vide pas correctement entre deux requêtes différentes.
- Des problèmes de déconnexion intempestives du socket.
- Un problème de scrolling des pages web récupérées qui défilent à l'écran en boucle sans s'arrêter.
Nous avons finalement réussi à finir le projet et à proposer quelque chose de fonctionnel.
Durant la dernière semaine nous avons aussi du préparer le tournage de la vidéo et rédiger le rapport final disponible ci-dessous.
Fichiers Rendus
Rapport du projet : Fichier:Rapport minitel.pdf
Code du projet : https://archives.plil.fr/tlopez/3615_Facebook