diff --git a/Protocole/correction_etape_A.py b/Protocole/correction_etape_A.py new file mode 100644 index 0000000000000000000000000000000000000000..f341015e68b33d8f9f5f4d98ece6a64d9550b6b1 --- /dev/null +++ b/Protocole/correction_etape_A.py @@ -0,0 +1,142 @@ +''' +OC Robotique 2025 +Template pour librairie Protocole Réseau pour Micro:bit + +Auteur·ice : Vincent Namy +Version : 1.0 +Date : 29.01.25 +''' + +#### Libraries #### +from microbit import * +import radio + +#### Variables globales #### +seqNum = 0 +tryTime = 100 +Timeout = 300 +ackMsgId = 255 + +#### Start radio module #### +radio.config(channel=7, address=50) +radio.on() + + +#### Classe Message #### +class Message: + def __init__(self, dest:int, exped:int, seqNum:int, msgId:int, payload:List[int], crc:int): + ''' + Constructeur de l'objet Message à partir des paramètres + Parameters: + dest:int, exped:int, seqNum:int, msgId:int, payload:List[int], crc:int + Returns: + self(Message): objet Message contenant les paramètres + ''' + self.exped = exped + self.dest = dest + self.seqNum = seqNum + self.msgId = msgId + self.payload = payload + self.crc = crc + def msgStr(self): + ''' + Crée une string contenant les détails du message + Parameters: + self(Message): objet message + Returns: + msgStr(str): string contenant les détails du message + ''' + return str(self.exped)+ " -> "+ str(self.dest)+ "n[" + str(self.seqNum)+ "] "+ " : type "+ str(self.msgId)+" : " +str(self.payload)+ " (crc="+ str(self.crc)+")" + +#### Toolbox #### +def bytes_to_int(bytesPayload:bytes): + ''' + Convert bytes object to List[int] + Parameters: + bytesPayload(bytes): payload in bytes format + Returns: + intPayload(List[int]): payload in int format + ''' + intPayload = [] + for i in bytesPayload: + intPayload.append(ord(bytes([i]))) + return intPayload + + +def int_to_bytes(intPayload:List[int]): + ''' + Convert List[int] to bytes object + Parameters: + intPayload(List[int]): payload in int format + Returns: + bytesPayload(bytes): payload in bytes format + ''' + return bytes(intPayload) + + +#### Fonctions réseaux #### +def ack_msg(msg : Message): + ''' + Envoie un ack du message recu. + 1) Création d'une liste de int correspondant au ack dans l'ordre du protocole + 2) Conversion en bytes + 3) Envoi + Parameters: + msg(Message): Objet Message contenant tous les paramètres du message à acker + ''' + pass # à compléter + + +def receive_ack(msg: Msg): + ''' + Attend un ack correspondant au message recu. + 1) Récupère les messages recus + 2) Conversion trame en objet Message + 3) Check si le ack correspond + Parameters: + msg(Message): Objet Message duquel on attend un ack + Returns: + acked(bool): True si message acké, sinon False + ''' + pass # à compléter + + +def send_msg(msgId:int, payload:List[int], userId:int, dest:int): + global seqNum + + msg = [msgId] + payload + radio.send_bytes(int_to_bytes(msg)) + + +def receive_msg(userId:int): + + new_trame = radio.receive_bytes() + if new_trame: + trame = bytes_to_int(new_trame) + msgObj = Message( None, None, None, trame[2], trame[3], None) + + return msgObj + +if __name__ == '__main__': + + userId = 0 + destId = 2 + + # Main + while True: + # Messages à envoyer + if button_a.was_pressed(): + send_msg(1,[60],userId, destId) + + + # Reception des messages + m = receive_msg(userId) + if m and m.msgId==1 and m.payload == 60: + display.show(Image.SQUARE) + sleep(200) + display.clear() + + + + + diff --git a/Protocole/correction_etape_B.py b/Protocole/correction_etape_B.py new file mode 100644 index 0000000000000000000000000000000000000000..7bd218f45038472df03b548b42e6c99771816e05 --- /dev/null +++ b/Protocole/correction_etape_B.py @@ -0,0 +1,142 @@ +''' +OC Robotique 2025 +Template pour librairie Protocole Réseau pour Micro:bit + +Auteur·ice : Vincent Namy +Version : 1.0 +Date : 29.01.25 +''' + +#### Libraries #### +from microbit import * +import radio + +#### Variables globales #### +seqNum = 0 +tryTime = 100 +Timeout = 300 +ackMsgId = 255 + +#### Start radio module #### +radio.config(channel=7, address=50) +radio.on() + + +#### Classe Message #### +class Message: + def __init__(self, dest:int, exped:int, seqNum:int, msgId:int, payload:List[int], crc:int): + ''' + Constructeur de l'objet Message à partir des paramètres + Parameters: + dest:int, exped:int, seqNum:int, msgId:int, payload:List[int], crc:int + Returns: + self(Message): objet Message contenant les paramètres + ''' + self.exped = exped + self.dest = dest + self.seqNum = seqNum + self.msgId = msgId + self.payload = payload + self.crc = crc + def msgStr(self): + ''' + Crée une string contenant les détails du message + Parameters: + self(Message): objet message + Returns: + msgStr(str): string contenant les détails du message + ''' + return str(self.exped)+ " -> "+ str(self.dest)+ "n[" + str(self.seqNum)+ "] "+ " : type "+ str(self.msgId)+" : " +str(self.payload)+ " (crc="+ str(self.crc)+")" + +#### Toolbox #### +def bytes_to_int(bytesPayload:bytes): + ''' + Convert bytes object to List[int] + Parameters: + bytesPayload(bytes): payload in bytes format + Returns: + intPayload(List[int]): payload in int format + ''' + intPayload = [] + for i in bytesPayload: + intPayload.append(ord(bytes([i]))) + return intPayload + + +def int_to_bytes(intPayload:List[int]): + ''' + Convert List[int] to bytes object + Parameters: + intPayload(List[int]): payload in int format + Returns: + bytesPayload(bytes): payload in bytes format + ''' + return bytes(intPayload) + + +#### Fonctions réseaux #### +def ack_msg(msg : Message): + ''' + Envoie un ack du message recu. + 1) Création d'une liste de int correspondant au ack dans l'ordre du protocole + 2) Conversion en bytes + 3) Envoi + Parameters: + msg(Message): Objet Message contenant tous les paramètres du message à acker + ''' + pass # à compléter + + +def receive_ack(msg: Msg): + ''' + Attend un ack correspondant au message recu. + 1) Récupère les messages recus + 2) Conversion trame en objet Message + 3) Check si le ack correspond + Parameters: + msg(Message): Objet Message duquel on attend un ack + Returns: + acked(bool): True si message acké, sinon False + ''' + pass # à compléter + + +def send_msg(msgId:int, payload:List[int], userId:int, dest:int): + global seqNum + + msg = [dest, userId, msgId] + payload + radio.send_bytes(int_to_bytes(msg)) + + +def receive_msg(userId:int): + + new_trame = radio.receive_bytes() + if new_trame: + trame = bytes_to_int(new_trame) + msgObj = Message( trame[0], trame[1], None, trame[2], trame[3], None) + + if msgObj and msgObj.dest == destId: + return msgObj + +if __name__ == '__main__': + + userId = 0 + destId = 2 + + # Main + while True: + # Messages à envoyer + if button_a.was_pressed(): + send_msg(1,[60],userId, destId) + + + # Reception des messages + m = receive_msg(userId) + if m and m.msgId==1 and m.payload == 60: + display.show(Image.SQUARE) + sleep(200) + display.clear() + + + + diff --git a/Protocole/protocole.py b/Protocole/protocole.py index f257921ea1caee313ecba3a7f08a70e68e86a0ad..cff2c9da69b07f8c91cf3aab6f28f96251dd0493 100644 --- a/Protocole/protocole.py +++ b/Protocole/protocole.py @@ -1,15 +1,19 @@ ''' Protocole Réseau Pour Micro:bit OC Robotique 2025 Auteur·ice : Vincent Namy -Version : 1.3 -Date : 29.1.25 +Version : 1.4 +Date : 03.03.25 ''' +encryption = False + #### Libraries #### from microbit import * import radio -import random -import aes + +if encryption: + import random + import aes #### Variables globales #### seqNum = 0 @@ -22,9 +26,10 @@ radio.config(channel=7, address=50) radio.on() #### Init AES #### -key = bytes([156, 110, 239, 52, 206, 138, 164, 35, 3, 76, 3, 60, 84, 199, 63, 253])#bytes([ random.getrandbits(8) for _ in range(16)]) -iv = bytes([ 0 for _ in range(16)]) -cipher = aes.AES(key) +if encryption: + key = bytes([156, 110, 239, 52, 206, 138, 164, 35, 3, 76, 3, 60, 84, 199, 63, 253]) # Generate yours with bytes([ random.getrandbits(8) for _ in range(16)]) + iv = bytes([ 0 for _ in range(16)]) + cipher = aes.AES(key) @@ -85,37 +90,45 @@ def msg_to_trame(rawMsg : Message): ''' Crée une trame à partir des paramètres d'un objet Message afin de préparer un envoi. 1) Création d'une liste de int dans l'ordre du protocole - 2) Conversion en bytes + 2) Encryption si nécessaire + 3) Conversion en bytes Parameters: rawMsg(Message): Objet Message contenant tous les paramètres du message à envoyer Returns: trame(bytes): payload convertie au format bytes ''' l = [rawMsg.dest, rawMsg.exped, rawMsg.seqNum, rawMsg.msgId] + rawMsg.payload - rawMsg.crc = sum(l)%256 - return int_to_bytes(l + [rawMsg.crc]) + rawMsg.crc = sum(l)%256 + trame = l + [rawMsg.crc] + + if encryption: + trame = cipher.encrypt_cfb(trame, iv) + + return int_to_bytes(trame) def trame_to_msg(trame : bytes, userId :int): ''' Crée un objet Message à partir d'une trame brute recue. 1) Conversion de bytes en liste de int - 2) Découpage de la liste de int dans l'ordre du protocole pour remplir l'objet Message - 3) Check du CRC et du destinataire + 2) Decryption si nécessaire + 3) Découpage de la liste de int dans l'ordre du protocole pour remplir l'objet Message + 4) Check du CRC et du destinataire Parameters: trame(bytes): payload au format bytes Returns: msgObj(Message): Objet Message contenant tous les paramètres du message recu si crc et destinataire ok, sinon None ''' trame = bytes_to_int(trame) - print(trame) + + if encryption: + trame = bytes_to_int(cipher.decrypt_cfb(trame, iv)) + msgObj = Message(trame[0], trame[1], trame[2], trame[3], trame[4:-1], trame[-1]) if msgObj.crc == sum(trame[:-1])%256: - if msgObj.dest != userId : -# print("Not for me") + if msgObj.dest != userId : # Not for me return None else: -# print(msgObj.msgStr()) return msgObj @@ -128,9 +141,10 @@ def ack_msg(msg : Message): Parameters: msg(Message): Objet Message contenant tous les paramètres du message à acker ''' - ack = [msg.exped, msg.dest, msg.seqNum, ackMsgId] - ack += [sum(ack)%256] - radio.send_bytes(cipher.encrypt_cfb(int_to_bytes(ack), iv)) + + msgAck = Message(msg.exped, msg.dest, msg.seqNum, ackMsgId, [],0) + trame = msg_to_trame(msgAck) + radio.send_bytes(trame) def receive_ack(msg: Msg): @@ -146,13 +160,8 @@ def receive_ack(msg: Msg): ''' new_trame = radio.receive_bytes() if new_trame: - decrypted = cipher.decrypt_cfb(new_trame, iv) - msgRecu = trame_to_msg(decrypted, msg.exped) -# print("Reçu Ack : ", msgRecu.msgStr()) - if msgRecu: - return msgRecu.exped == msg.dest and msgRecu.dest == msg.exped and msgRecu.seqNum == msg.seqNum and msgRecu.msgId == ackMsgId - else: - return False + msgRecu = trame_to_msg(new_trame, msg.exped) + return msgRecu and msgRecu.exped == msg.dest and msgRecu.dest == msg.exped and msgRecu.seqNum == msg.seqNum and msgRecu.msgId == ackMsgId else: return False @@ -181,16 +190,14 @@ def send_msg(msgId:int, payload:List[int], userId:int, dest:int): acked = False t0 = running_time() print("Envoyé : ", msg.msgStr()) + print(msg.msgStr()) while not acked and running_time()-t0 < Timeout: -# print("envoi") - trame = msg_to_trame(msg) - encrypted = cipher.encrypt_cfb(trame, iv) - radio.send_bytes(encrypted) + trame = msg_to_trame(msg) + radio.send_bytes(trame) sleep(tryTime//2) display.clear() sleep(tryTime//2) acked = receive_ack(msg) -# print("acked : ", acked) # print(running_time()-t0) seqNum += 1 @@ -209,10 +216,8 @@ def receive_msg(userId:int): ''' new_trame = radio.receive_bytes() if new_trame: - decrypted = cipher.decrypt_cfb(new_trame, iv) - msgRecu = trame_to_msg(decrypted, userId) - #print("Reçu : ", msgRecu.msgStr()) - if msgRecu.msgId != ackMsgId: # Ajouter un if msgRecu + msgRecu = trame_to_msg(new_trame, userId) + if msgRecu and msgRecu.msgId != ackMsgId: ack_msg(msgRecu) return msgRecu @@ -220,13 +225,13 @@ def receive_msg(userId:int): if __name__ == '__main__': import music - userId = 0 + userId = 1 while True: # Messages à envoyer - destId = 1 + destId = 0 if button_a.was_pressed(): - send_msg(1,[60],userId, destId) + print(send_msg(1,[60],userId, destId)) elif button_b.was_pressed(): send_msg(1,[120],userId, destId)