// ========================== programme Rascar_annonce ============================== // Ce NodeMCU /ESP-12 fonctionne en mode point d'accès pour les détecteurs embarqués, // et en même temps mode station vis-à-vis de la centrale DCC. // Le programme reçoit les paquets UDP envoyés par les détecteurs embarqués, // les traite, puis déclenche une action (par exemple: annnonce d'entrée en gare) // ou pour tests, au PC avec Packet Sender // ================================================================================== #include #include // informations remontées au PC pour affichage #define sp Serial.print #define spl Serial.println // commandes reçues sur port série int NbMots; String Mots[5]; // mode point d'accès pour les détecteurs embarqués #define AP_SSID "rascar" #define AP_PASS "12345678" // mode station vers la centrale. PC + Packet Sender pour test #define WIFI_SSID "Livebox-xxxx" #define WIFI_PASS "abcdefg" // pour récupération des paquets UDP const uint16_t PORT = 50000; // Port d'écoute UDP const uint16_t BUFFER_SIZE = 512; // Taille du tampon de réception char buffer[BUFFER_SIZE]; // Tampon de réception uint16_t len = 0;// Taille du paquet reçu; // instanciation du serveur UDP WiFiUDP udp; void setup() { // =================================================================================== setup Serial.begin(19200); spl(); // ------------------------------------------------------------------ démarrage du point d'accès WiFi.mode(WIFI_AP_STA); IPAddress local_IP(192,168,4,1); // adresse IP du point d'accès IPAddress gateway(192,168,4,1); IPAddress subnet(255,255,255,0); WiFi.softAPConfig(local_IP, gateway, subnet); // fixe l'adresse IP du point d'accès //WiFi.softAPConfig({192,168,4,1},{192,168,4,1},{255,255,255,0}); // ou directement WiFi.softAP(AP_SSID, AP_PASS); // démarrage du point d'accès sp("adresse IP du réseau "); sp(AP_SSID); sp(" : "); spl(WiFi.softAPIP()); // ------------------------------------------------------------ mode station sur la centrale DCC // pour simplifier, utilisation de la même adresse MAC (sinon bloquée par la box) const uint8_t mac[6] = {0x2C, 0x3A, 0xE8, 0x26, 0xA3, 0x54}; // "2c:3a:e8:26:a3:54" // changement de l'adresse MAC cf: https://circuits4you.com/2017/12/31/how-to-change-esp8266-mac-address/ spl(""); sp("ancienne adresse MAC: "); sp(WiFi.macAddress()); // adresse MAC en cours wifi_set_macaddr(0, const_cast(mac)); //changement MAC address pour Livebox sp(" nouvelle adresse MAC: "); spl(WiFi.macAddress()); // ------------------------------------------------------------------------- connexion au PC WiFi.begin(WIFI_SSID, WIFI_PASS); // connexion au réseau local domestique sp("connection à "); spl(WIFI_SSID); while (WiFi.status() != WL_CONNECTED) { delay(100); sp("."); } udp.begin(50000); // démarre l'écoute sur port 50000 spl(); spl("Connecté!"); sp("adresse IP sur réseau "); sp(AP_SSID); sp(" : "); spl(WiFi.softAPIP()); sp("adresse IP sur réseau "); sp(WIFI_SSID); sp(" : "); spl(WiFi.localIP()); spl(""); } void loop() { // =================================================================================== loop if (udp.parsePacket() > 0) { readPacket(); } // réception des paquets UDP pour test if (Serial.available() > 0) { ReceptionSerie(); } // réception des commandes sur port série } // ===================================================================================== sous programmes void ReceptionSerie(){ // ------------------ réception des octets un par un sur port série, pour tests char X; X = Serial.read(); //réception d'un caractère switch (X){ // ********************** trois cas: space, line feed, ou autre caractère case (32):{++NbMots;} break; // ********************************************* espace case 10: { // **************************************************** LF = fin de message if (Mots[0] == "?") { // --------------------------------------------- commande ? spl("commande ?"); sp("adresse IP sur réseau "); sp(AP_SSID); sp(" : "); spl(WiFi.softAPIP()); sp("adresse IP sur réseau "); sp(WIFI_SSID); sp(" : "); spl(WiFi.localIP()); sp(""); } if(Mots[0] == "!") { // ---------------------- tests de communication - commande ! spl("commande !"); // sendPacket("test", 4, {192,168,4,100},50000); // test sendPacket("test", 4, {192,168,1,10},21105); // envoi au PC / Packet Sender } // ------------------------------------------------------------- fin de commande, reset Mots[0]=""; Mots[1]=""; Mots[2]=""; Mots[3]=""; NbMots = 0; break; // fin de LF } default:{ // ****************************************** autre caractère: concaténation Mots[NbMots] = Mots[NbMots] + X;}; break; } } // ==================================================================== récupération et affichage d'un paquet void readPacket() { len = udp.available(); udp.read(buffer, len); // Mise en tampon du paquet TraitementMessage(); // traitement du paquet } // ==================================================================================== envoi d'un paquet UDP void sendPacket(const char content[], int longueur, IPAddress ip, uint16_t port) { // avec longueur en INT //void sendPacket(char content[], IPAddress ip, uint16_t port) { // avec zéro à la fin sp("envoi de "); sp(longueur); sp(" octets à "); sp(ip); sp(":"); spl(port); delay(10); udp.beginPacket(ip, port); udp.write(content, longueur); udp.endPacket(); } // ================================================================================= traitement des messages void TraitementMessage(){ AffichageMessage(); // pour test // le numéro du train peut être calculé d'après l'adresse IP du détecteur, ou contenue dans le message //sp("le train "); spl(udp.remoteIP()[3]); spl(""); // d'après l'adresse IP du détecteur sp("train "); sp(buffer[0],DEC); sp (" balise "); spl (buffer[1],DEC); spl(""); // d'après le message // yapuka activer le dispositif d'annonce! spl("retransmission..."); delay(10); sendPacket("retransmission", 14, {192,168,1,10},50000); // envoi au PC / Packet Sender pour test delay(10); } // ================================================================================== affichage d'un message void AffichageMessage() { sp("reçu "); sp(len); sp(" octets de "); sp(udp.remoteIP()); sp(":"); sp(udp.remotePort()); sp(" soit: "); for(int i=1; i<=len; i++) {PrtHex(buffer[i-1]); sp(" ");} spl(""); } // ======================================================================= affichage en hexadécimal amélioré void PrtHex(char X) { if (X<16){sp("0");} sp(X,HEX); }