2026-03-05 08:37:38 +01:00

198 lines
5.9 KiB
C++

#include <Arduino.h>
#include <SPI.h>
#include "SimpleWiNo.h"
#include <M5Stack.h>
//Objet Wino
SimpleWiNo wino;
//Constantes de configuration des noeuds
#define ADRESSE_CLUSTER 0x4A89
#define ADRESSE_NOEUD 0x0002
#define CANAL 7
//Variables pour le paquet
uint8_t rxbuf[40]; //Buffer de reception
uint8_t packetLenRX; //Longueur du paquet reçu
uint16_t adresseMacSource; //Adresse de couche 2 du noeud source
uint16_t adresseIpSource; //Adresse de couche 3 du noeud source
uint16_t adresseMulticast; //Adresse multicast reçue
//Propriétés du paquet
#define ADRESSE_MULTICAST 0x7878
#define TTL_MAX 7 //Time To Live avant expiration
//Indices des champs du paquet (format paquet)
#define CHAMP_ADRESSE_DST 0 //Position de l'adresse de destination
#define CHAMP_TTL 2 //Position du TTL dans le paquet
#define CHAMP_ADRESSE_SRC 3 //Position du champ d'adressage
#define CHAMP_NUM_SEQ 5 //Position du numéro de séquence
#define CHAMP_MIN_PAYLOAD 6 //Position du premier octet de la payload
//Mémorisation des paquets
//Nombre de paquets maximums mémorisables
#define NB_PAQUET_MEM 10
//Structure pour l'identification
struct identifiant{
uint16_t srcAddr;
uint8_t sqn;
};
typedef struct identifiant IDENTIFIANT;
uint8_t indiceMemId=0; //Indice pour la mise à jour dans le tableau
IDENTIFIANT idRecu; //Identifiant courant du paquet reçu
IDENTIFIANT tabId[NB_PAQUET_MEM]; //Tableau d'identifiants
//Procédures pour la mémorisation
//Initialisation du tableau d'identifiants
void initTabId(IDENTIFIANT tab[]){
for(int i=0; i<NB_PAQUET_MEM; i++){
tab[i].srcAddr=0xFFFF;
tab[i].sqn=255;
}
}
//Affichage des id du tableau
void AfficheId(IDENTIFIANT tab[]){
for(int i=0; i<NB_PAQUET_MEM; i++){
M5.Lcd.printf("{%02X, %02X}", tab[i].srcAddr, tab[i].sqn);
Serial.printf("{%02X, %02X}", tab[i].srcAddr, tab[i].sqn);
}
M5.Lcd.println();
Serial.println();
}
//Ajout d'un nouvel identifiant dans le tableau
//L'indice du tableau suit un modulo pour reboucler dans les mises à jour
//Afin de ne garder que les derniers NB_PAQUET_MEM paquets
void ajoutTabId(IDENTIFIANT id, IDENTIFIANT tab[], uint8_t* indice){
tab[*indice]=id;
*indice=(*indice+1)%NB_PAQUET_MEM;
}
//Fonction vérifiant si l'id du paquet arrivé a déjà été routé
//Si c'est le cas la fonction renvoi 1 (VRAI)
//Sinon, elle renvoi 0 (FAUX)
int PaquetDejaRoute(IDENTIFIANT id, IDENTIFIANT tab[]){
for(int i=0; i<NB_PAQUET_MEM; i++){
//Un élément du tableau correspond
if((tab[i].srcAddr==id.srcAddr) && (tab[i].sqn==id.sqn)){
return 1;
}
}
return 0;
}
//Procédure d'affichage de la payload reçue
//À partir de l'indice de début de payload uniquement
void afficherPayload(uint8_t indiceDebut, uint8_t longueur, uint8_t donnees[]){
M5.Lcd.printf("Payload : ");
Serial.printf("Payload : ");
for(int i=indiceDebut; i<longueur; i++){
M5.Lcd.printf("|%02X", donnees[i]);
Serial.printf("|%02X", donnees[i]);
}
M5.Lcd.println("|");
Serial.println("|");
}
void setup() {
//Démarage M5
M5.begin();
M5.Power.begin();
Serial.println("==Relais sprint 5==");
M5.Lcd.println("==Relais sprint 5===");
delay(3000);
//Demarage wino
wino.init();
//Adresse cluster
wino.set(NODE_PANID, ADRESSE_CLUSTER);
//Adresse noeud
wino.set(NODE_SHORT_ADDRESS, ADRESSE_NOEUD);
//Fréquence de travail
wino.set(NODE_CHANNEL, CANAL);
//Initialisation du tableau de mémoire des identifiants
initTabId(tabId);
}
void loop() {
wino.process();
//Test Reception
if(wino.recv(&adresseMacSource, rxbuf, &packetLenRX) /*&& (adresseMacSource!=1)*/){
//Affichage des éléments du paquet reçu
M5.Lcd.println("=====Reception=====");
Serial.println("=====Reception=====");
//Affichage du noeud source
adresseIpSource=wino.decodeUi16(&rxbuf[CHAMP_ADRESSE_SRC]);
M5.Lcd.printf("MAC SRC : %X | ", adresseMacSource);
Serial.printf("MAC SRC : %X | ", adresseMacSource);
M5.Lcd.printf("IP SRC : %X \n", adresseIpSource);
Serial.printf("IP SRC : %X \n", adresseIpSource);
//Affichage Adresse Multicast
adresseMulticast=wino.decodeUi16(&rxbuf[CHAMP_ADRESSE_DST]);
M5.Lcd.printf("Adresse Multicast : %X \n", adresseMulticast);
Serial.printf("Adresse Multicast : %X \n", adresseMulticast);
//Affichage TTL
M5.Lcd.printf("TTL : %d \n", rxbuf[CHAMP_TTL]);
Serial.printf("TTL : %d \n", rxbuf[CHAMP_TTL]);
//Incrémentation TTL
rxbuf[CHAMP_TTL]+=1;
//Affichage du numéro de séquence
M5.Lcd.printf("Num Seq : %d \n", rxbuf[CHAMP_NUM_SEQ]);
Serial.printf("Num Seq : %d \n", rxbuf[CHAMP_NUM_SEQ]);
//Affichage Payload
afficherPayload(CHAMP_MIN_PAYLOAD, packetLenRX, rxbuf);
//Test pour la réemission
//Le paquet n'a pas été émis par le noeud lui-même
if(adresseIpSource!=ADRESSE_NOEUD){
//Même adresse multicast et TTL inférieur au max
if((adresseMulticast==ADRESSE_MULTICAST) && (rxbuf[CHAMP_TTL]<=TTL_MAX)){
//Récupération de l'identifiant du paquet recu
idRecu.srcAddr=adresseIpSource;
idRecu.sqn=rxbuf[CHAMP_NUM_SEQ];
//Test si le paquet n'a pas déjà été reçu
if(!PaquetDejaRoute(idRecu, tabId)){
M5.Lcd.println("=====Reemission Paquet=====");
Serial.println("=====Reemission Paquet=====");
//Ajout du nouvel id dans le tableau
ajoutTabId(idRecu, tabId, &indiceMemId);
//Réemission du paquet
wino.send(0xFFFF, rxbuf, packetLenRX);
//Affichage des id mémorisés
AfficheId(tabId);
}
else{
M5.Lcd.println("===Deja Recu===");
Serial.println("===Deja Recu===");
}
}
else{
M5.Lcd.println("Adresse multicast incorecte ou TTL depasse");
Serial.println("Adresse multicast incorecte ou TTL depasse");
}
}
else{
M5.Lcd.println("===Paquet emis par le noeud===");
Serial.println("===Paquet emis par le noeud===");
}
}
}