Protocoles de communication
Comment deux ordinateurs communiquent-ils ?
Code de base
Ce code permet uniquement d'échanger des messages par radio. Il comporte des problèmes majeurs :
- l'ensemble est inintelligible
- on ne sait pas qui est le destinataire ni l'émetteur
from microbit import *
import radio
radio.on() # Active la radio
radio.config(channel=10) # Définit un canal (10 ici)
while True:
if button_a.was_pressed():
msg_envoi = input("Message ?")
radio.send(msg_envoi) # Envoie un message
message = radio.receive() # Permet de vérifier régulièrement la réception d'un message
if message:
print(message) # Affiche le message reçu dans la console
Définition d'un protocole
Version 1
- Le séparateur utilisé est le symbole monétaire générique
¤
- La trame est définie ainsi :
DESTINATAIRE¤ÉMETTEUR¤MESSAGE
- Le destinataire, l'émetteur et le message ne peuvent pas être vides
ping
est un nom réservé- On ignore les messages qui ne respectent pas ce protocole
Implémentation du protocole
On ajoute les éléments suivants :
- constantes :
SEP
pour le séparateur,PSEUDO
pour le nom de l'émetteur - utilisation de la fonction
input()
pour pouvoir saisir le pseudo du destinataire - concaténation des chaînes de caractères nécessaires à la création de la trame
- on ignore les messages qui ne respectent pas le protocole :
- utilisation de
split()
pour diviser le message reçu - si on obtient trois parties, on considère que la première est le destinataire, la deuxième est l'émetteur, la troisième est le message
- chacune des trois parties ne doit pas être égale à une chaîne de caractères vide
''
- utilisation de
from microbit import *
import radio
radio.on() # Active la radio
radio.config(channel=10) # Définit un canal (10 ici)
SEP = '¤'
PSEUDO = 'Mathieu'
while True:
if button_a.was_pressed():
msg_envoi = input("Message ?")
destinataire = input("Destinataire ?")
radio.send(destinataire+SEP+PSEUDO+SEP+msg_envoi) # Envoie un message
trame = radio.receive() # Permet de vérifier régulièrement la réception d'un message
if trame:
parts = trame.split(SEP)
if len(parts) == 3 and parts[0] != '' and parts[1] != '' and parts[2] != '':
print(parts[2])
Affichage des message qui nous concernent
On ne veut pas polluer notre affichage avec des messages qui ne nous sont pas adressés.
On définit donc notre nom d'utilisateur, et on affiche seulement les messages qui nous sont adressés.
On définit donc notre nom d'utilisateur, et on affiche seulement les messages qui nous sont adressés.
from microbit import *
import radio
radio.on() # Active la radio
radio.config(channel=10) # Définit un canal (10 ici)
SEP = '¤'
PSEUDO = 'Mathieu'
while True:
if button_a.was_pressed():
msg_envoi = input("Message ?")
destinataire = input("Destinataire ?")
radio.send(destinataire+SEP+PSEUDO+SEP+msg_envoi) # Envoie un message
trame = radio.receive() # Permet de vérifier régulièrement la réception d'un message
if trame:
parts = trame.split(SEP)
if len(parts) == 3 and parts[0] != '' and parts[1] != '' and parts[2] != '':
if parts[0] == PSEUDO:
print(parts[2])
Signaler sa présence sur le réseau (WIP)
Nous envoyons actuellement des messages aux personnes qui sont à portée de voix, qui sont capables de nous donner l'information de leur pseudonyme sur le réseau. Nous allons ajouter la fonctionnalité permettant de signaler sa présence sur le réseau, grâce à l'utilisation d'une commande, que nous appellerons
"Envoyer un ping" revient à envoyer une trame au destinataire
ping
.
"Envoyer un ping" revient à envoyer une trame au destinataire
ping
, avec le message correspondant à notre pseudo
.Cela signifie que
ping
devient un nom réservé : son utilisation comme pseudonyme doit être interdite.from microbit import *
import radio
radio.on() # Active la radio
radio.config(channel=10) # Définit un canal (10 ici)
SEP = '¤'
PSEUDO = 'Mathieu'
while True:
if button_a.was_pressed():
msg_envoi = input("Message ?")
dest = input("Destinataire ?")
radio.send(dest+SEP+PSEUDO+SEP+msg_envoi) # Envoie une trame
if button_b.was_pressed():
radio.send('ping'+SEP+PSEUDO) # Envoie un ping pour signaler sa présence
trame = radio.receive() # Permet de vérifier régulièrement la réception d'un message
if trame:
parts = trame.split(SEP)
if len(parts) == 3 and parts[0] != '' and parts[1] != '' and parts[2] != '':
if parts[0] == PSEUDO:
print(parts[2])
Prise en compte du ping des autres
Nous devons prendre en compte les
ping
et ajouter l'identifiant qui s'est signalé à nous à une liste, pour faciliter son utilisation.On utilise un dictionnaire pour stocker les pseudos, car un dictionnaire, par construction, ne peut pas avoir deux clés identiques. Cela nous permet donc :
- d'éviter les doublons
- de stocker une valeur associée à chaque pseudo (utile pour la suite)
from microbit import *
import radio
radio.on() # Active la radio
radio.config(channel=10) # Définit un canal (10 ici)
SEP = '¤'
PSEUDO = 'Mathieu'
annuaire = {}
while True:
if button_a.was_pressed():
msg_envoi = input("Message ?")
dest = input("Destinataire ?")
radio.send(dest+SEP+PSEUDO+SEP+msg_envoi) # Envoie une trame
if button_b.was_pressed():
radio.send('ping'+SEP+PSEUDO) # Envoie un ping pour signaler sa présence
print(annuaire)
trame = radio.receive() # Permet de vérifier régulièrement la réception d'un message
if trame:
parts = trame.split(SEP)
if len(parts) == 2 and parts[0] == 'ping' and parts[1] != '':
annuaire[parts[1]] = 'toto'
if len(parts) == 3 and parts[0] != '' and parts[1] != '' and parts[2] != '':
if parts[0] == PSEUDO:
print(parts[2])
Automatisation du ping
On utilisera la fonction
running_time()
disponible sur les cartes micro:bit, ainsi que l'opérateur modulo %
.Explication de la ligne
if running_time() % 5000 < 10
: running_time()
nous donne le nombre de millisecondes écoulées depuis le démarrage de la carte micro:bitrunning_time() % 5000
nous permet d'obtenir le reste de la division par 5000- si ce reste est inférieur à
10ms
, alors nous venons de dépasser 5 secondes depuis moins de 10 millisecondes
ping
toutes les 5 secondesfrom microbit import *
import radio
radio.on() # Active la radio
radio.config(channel=10) # Définit un canal (10 ici)
SEP = '¤'
PSEUDO = 'Mathieu'
annuaire = {}
while True:
if running_time() % 5000 < 10:
radio.send('ping'+SEP+PSEUDO)
sleep(10) # mise en pause pendant 10ms pour éviter d'envoyer le ping plusieurs fois d'un coup
if button_a.was_pressed():
msg_envoi = input("Message ?")
dest = input("Destinataire ?")
radio.send(dest+SEP+PSEUDO+SEP+msg_envoi) # Envoie une trame
if button_b.was_pressed():
print(annuaire)
trame = radio.receive() # Permet de vérifier régulièrement la réception d'un message
if trame:
parts = trame.split(SEP)
if len(parts) == 2 and parts[0] == 'ping' and parts[1] != '':
annuaire[parts[1]] = 'toto'
if len(parts) == 3 and parts[0] != '' and parts[1] != '' and parts[2] != '':
if parts[0] == PSEUDO:
print(parts[2])
Sélection du destinataire
Le dictionnaire créé à l'étape 6 contient les pseudos des différents utilisateurs du réseau de communication. On peut utiliser ce dictionnaire pour permettre de choisir le destinataire dans une liste, plutôt que d'avoir à recopier son pseudo à chaque fois.
Attention, en fonction des
ping
reçus, la liste des utilisateurs va forcément évoluer au fil du temps. Il faut donc la créer à partir du dictionnaire à chaque fois qu'on a besoin de choisir un utilisateur.from microbit import *
import radio
radio.on() # Active la radio
radio.config(channel=10) # Définit un canal (10 ici)
SEP = '¤'
PSEUDO = 'Mathieu'
annuaire = {}
def choix_destinataire():
utilisateurs = { str(index): pseudo for index,pseudo in enumerate(annuaire)}
print(utilisateurs)
choix = input("Utilisateur ?"")
return utilisateurs[choix]
while True:
if running_time() % 5000 < 10:
radio.send('ping'+SEP+PSEUDO)
sleep(10) # mise en pause pendant 10ms pour éviter d'envoyer le ping plusieurs fois d'un coup
if button_a.was_pressed():
msg_envoi = input("Message ?")
dest = choix_destinataire()
radio.send(dest+SEP+PSEUDO+SEP+msg_envoi) # Envoie une trame
if button_b.was_pressed():
print(annuaire)
trame = radio.receive() # Permet de vérifier régulièrement la réception d'un message
if trame:
parts = trame.split(SEP)
if len(parts) == 2 and parts[0] == 'ping' and parts[1] != '':
annuaire[parts[1]] = 'toto'
if len(parts) == 3 and parts[0] != '' and parts[1] != '' and parts[2] != '':
if parts[0] == PSEUDO:
print(parts[2])