me-no-dev / ESPAsyncUDP

Async UDP library for ESP8266

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Simple multicast scheme I can not get it working with ESPAsynUDP.

jirmjos opened this issue · comments

First of all, sorry by my poor english, and "newby" questions, but I hope anyone can understand enough my issue.

After several hours of testing I do not get a simple network schema where several esp modules need to listen a multicast UDP ip address (IP 239.1.2.3 ,port 1234) to a request with a simple parameter (2 bytes of data) that once evaluated the module that have the reply can (based on the evaluation of data received on the call) send a reply to the "caller" with other simple parameter (this time a single byte) like a response (I understand this time as unicast) to the module that has done that query through the mentioned multicast call.

I am using for the tests the own examples of the ESPAsynUDP library.

The problem is that although the multicast call to the server is received perfectly, I can not configure the client to be able to "listen" to the response that is forwarded on this server line at the end of multicast receive callback server function:

**if(udp.listenMulticast(IPAddress(239,1,2,3),` 1234)) {
.......
// reply to the client
packet.printf (" Got% u bytes of data ", packet.length ());)** 

I suppose maybe packet.printf() it is sent to a ip/port that does not match the one the client or is listening to.

Obviously the problem is at least that I do not understand which are the appropriate asyncUDP instrucctions on the client side to listen the unicast replyes from from the server.

The problem is complicated a little more, since I have the need for all modules to be "servers" and "clients" simultaneously.
That is, I need everyone to be "subscribed" to the multicast address to receive requests and when it is evaluated the query by each, only one of them will sent a reply to be forwarded to the one which has launched that query.

My question is what would be the appropriate "client" and "server" ESPAsynUDP functions scheme (based on the examples) that I should use and specifically how to properly configure multicast listeners and make directed unicast responses at same time to achieve my goal.

I can not combine all the propperly asynUDP instructions with multicast and unicast to make it work.

As side note, own "client" and "server" (not very appropriate to call them so given what I have said before that everyone must have both roles) IP address are static 192.168.1.99/24 and 192.168.1.101/24 with a gateway 192.168.1.1 (general network router) and wifi setup are propperly up and running fine in all modules.

Any help will be greatly appreciated.

regards

Have you looked at the library header? AsyncUDP has methods to send packets/replies to particular IP/Port (writeTo, sendTo, etc) that will actually unicast to the specified host :) and the host IP you can get from the packet (packet.remoteIP()). Maybe post some more simplified version of your code and some log :)

So many thanks for your reply @me-no-dev !
I insist that I'm a really newby in coding, so sorry about my huge lack of acknowledgement on this.
I'm trying to understand how to do it seeing library headers, but since I'm not a coder I cannot figure out how to properly manage the function calls.
I triyed udp,sendTo and udp.writeTo but having compiling messages that "not matching function for ESPAsyncUDP::writeTo or similar for udp.sendTo, mainly because I cannot "understand" how to use the in-build function and method calls for async udp and async packet objects.
And too I cannot understand why I have a packet "storm" .onPacket calls when try your simple examples.
Thats my skecthes on both ESP:
On both have the same base sketch because both need be client-server roles, but for clarify purposses I called server to one ESP (ESP-1) and Client the other (ESP-2).
Server - 192.168.1.101

#include <ESP8266WiFi.h>
#include "ESPAsyncUDP.h"

const char * ssid = "MYSSID";
const char * password = "MYKEY";

AsyncUDP udp;

void setup()
{
    Serial.begin(115200);
    Serial.println();
    Serial.println();
    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, password);
    if (WiFi.waitForConnectResult() != WL_CONNECTED) {
        Serial.println("WiFi Failed");
        while(1) {
            delay(1000);
        }
    }
     if(udp.listenMulticast(IPAddress(239,1,2,3), 1234)) {
        Serial.print("UDP Listening on IP: ");
        Serial.println(WiFi.localIP());
        udp.onPacket([](AsyncUDPPacket packet) {
            const char rsp[20]={"Reply from ESP-1"};
            Serial.print("UDP Packet Type: ");
            Serial.print(packet.isBroadcast()?"Broadcast":packet.isMulticast()?"Multicast":"Unicast");
            Serial.print(", From: ");
            Serial.print(packet.remoteIP());
            Serial.print(":");
            Serial.print(packet.remotePort());
            Serial.print(", To: ");
            Serial.print(packet.localIP());
            Serial.print(":");
            Serial.print(packet.localPort());
            Serial.print(", Length: ");
            Serial.print(packet.length());
            Serial.print(", Data: ");
            Serial.write(packet.data(), packet.length());
            Serial.println();
            //reply to the client
            //packet.printf("ESP-1 Got %u bytes of data", packet.length());
            packet.printf("Reply from ESP-1");
            //udp.writeTo("Reply from ESP-1" ,20 ,packet.remoteIP() ,packet.remotePort());
            //udp.sendTo("Reply from ESP-1" ,20 ,packet.remoteIP() ,packet.remotePort());
       });
        
    }
}

void loop()
{
    delay(5000);
    //Send multicast
   //udp.print("1");
}

Client - 192.168.1.99

#include <ESP8266WiFi.h>
#include "ESPAsyncUDP.h"

const char * ssid = "MYSSID";
const char * password = "MYKEY";

AsyncUDP udp;

void setup()
{
    Serial.begin(115200);
    Serial.println();
    Serial.println();
    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, password);
    if (WiFi.waitForConnectResult() != WL_CONNECTED) {
        Serial.println("WiFi Failed");
        while(1) {
            delay(1000);
        }
    }
        
    if(udp.listenMulticast(IPAddress(239,1,2,3), 1234)) {
        Serial.print("UDP Listening on IP: ");
        Serial.println(WiFi.localIP());
        udp.onPacket([](AsyncUDPPacket packet) {
            Serial.print("UDP Packet Type: ");
            Serial.print(packet.isBroadcast()?"Broadcast":packet.isMulticast()?"Multicast":"Unicast");
            Serial.print(", From: ");
            Serial.print(packet.remoteIP());
            Serial.print(":");
            Serial.print(packet.remotePort());
            Serial.print(", To: ");
            Serial.print(packet.localIP());
            Serial.print(":");
            Serial.print(packet.localPort());
            Serial.print(", Length: ");
            Serial.print(packet.length());
            Serial.print(", Data: ");
            Serial.write(packet.data(), packet.length());
            Serial.println();
            //reply to the client
            //packet.printf("ESP-2 Got %u bytes of data", packet.length());
            packet.printf("Reply from ESP-2");
        });
        
    }
}

void loop()
{
    delay(10000);
    //Send broadcast on port 1234
    udp.print("2");
} 

The serial console output on both shows the same packet storm, so only post one example:

UDP Listening on IP: 192.168.1.101
UDP Packet Type: Multicast, From: 192.168.1.99:1234, To: 239.1.2.3:1234, Length: 1, Data: 2
UDP Packet Type: Unicast, From: 192.168.1.99:1234, To: 192.168.1.101:1234, Length: 16, Data: Reply from ESP-2
UDP Packet Type: Unicast, From: 192.168.1.99:1234, To: 192.168.1.101:1234, Length: 16, Data: Reply from ESP-2
UDP Packet Type: Unicast, From: 192.168.1.99:1234, To: 192.168.1.101:1234, Length: 16, Data: Reply from ESP-2
UDP Packet Type: Unicast, From: 192.168.1.99:1234, To: 192.168.1.101:1234, Length: 16, Data: Reply from ESP-2
UDP Packet Type: Unicast, From: 192.168.1.99:1234, To: 192.168.1.101:1234, Length: 16, Data: Reply from ESP-2
UDP Packet Type: Unicast, From: 192.168.1.99:1234, To: 192.168.1.101:1234, Length: 16, Data: Reply from ESP-2
UDP Packet Type: Unicast, From: 192.168.1.99:1234, To: 192.168.1.101:1234, Length: 16, Data: Reply from ESP-2
....

As you can see with all I said I need a really huge help, because generally speaking I have no idea that what I'm doing :-(

Well, some more tries to get my goal, but so far than enough and sure a erroneous approach, but anyway I post it:
Seems I stop a little the onPacket storm calls, but not enough.
If I check before send more reply packets if packet.data() is yet received I can stop a little the continuously replies but not before a hundred of reply packets :-(

This is the new modified sketch (on both ESP):

const char * ssid = "MYSSID";
const char * password = "MYKEY";

AsyncUDP udp;
uint8_t* lastdatapacket;

void setup()
{
    Serial.begin(115200);
    Serial.println();
    Serial.println();
    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, password);
    if (WiFi.waitForConnectResult() != WL_CONNECTED) {
        Serial.println("WiFi Failed");
        while(1) {
            delay(1000);
        }
    }
     if(udp.listenMulticast(IPAddress(239,1,2,3), 1234)) {
        Serial.print("UDP Listening on IP: ");
        Serial.println(WiFi.localIP());
        udp.onPacket([](AsyncUDPPacket packet) {
            const char rsp[20]={"Reply from ESP-1"};
            Serial.print("UDP Packet Type: ");
            Serial.print(packet.isBroadcast()?"Broadcast":packet.isMulticast()?"Multicast":"Unicast");
            Serial.print(", From: ");
            Serial.print(packet.remoteIP());
            Serial.print(":");
            Serial.print(packet.remotePort());
            Serial.print(", To: ");
            Serial.print(packet.localIP());
            Serial.print(":");
            Serial.print(packet.localPort());
            Serial.print(", Length: ");
            Serial.print(packet.length());
            Serial.print(", Data: ");
            Serial.write(packet.data(), packet.length());
            Serial.println();
            //reply to the client
            //packet.printf("ESP-1 Got %u bytes of data", packet.length());
            if (packet.data() != lastdatapacket){
              packet.printf("Reply from ESP-1");
            }
            lastdatapacket=packet.data();
            //udp.writeTo("Reply from ESP-1" ,20 ,packet.remoteIP() ,packet.remotePort());
            //udp.sendTo("Reply from ESP-1" ,20 ,packet.remoteIP() ,packet.remotePort());
       });
        
    }
}

void loop()
{
    delay(5000);
    //Send multicast
   //udp.print("1");
} 

Can see the if comparison with packet.data() at end at .onPacket function to try stop the continuously replies.
But still is sending (and I suppose process the same number the onPacket callbacks) a hundred or more of message replies to continue again with the next multicast call received from the other ESP that triggers a new bunch of hundred of replies.

so... you should reply to a packet on the server only, else you go into loop client -> server -> client -> .... so on
client should udp.write() from loop and server should packet.write() from the handler. That way when the client sends a message to the server, the server will respond back, but the client would not again repond to the server's message

Ok. I think I get the idea but I don't know how to do it to have my goal.
I know that the replies with statements (printf) at onPackect() callbacks triggered from udp.print multicast call are causing that infinite loop of replies, but I can not understand so much how stop that and consequently I cannot imagine a way to do it since and even more because now I only just got the udp.print, packet.printf .statements working.

Because sketches are the same in both ESP (both need be server to reply calls and be clients to make the multicast requests), and at the end I need the same mixed client-server scheme (same sketch) for all ESP involved, I think this complicate a little more being able to make calls and answers without entering on infinite loops and I cannot see how implement that you say.

At this moment I cannot figure how to reply (only once) and where when packet is procesed at onPacket().
I figured out yesterday all that you comment, and this is why I put the if (packet.data() != lastdatapacket){ to try stop the loop client-server-client replies ... but it's not working and I tried but at this time cannot figure how to use propperly udp.write(), packet.write() and writeTo() that you comment, and all other methods from your library.
So sorry my huge lack of know, but I think my first problem is to form the proper call method for udp and packet objects (you can see that at the end two sentences to try to use .writeTo) that unfortunately I have not even been able to compile at all after much time tried to form the sentences to call in all the manner that I can think.

So basically first of all I'm totally stuck on how to properly use the calls to methods and properties to your library, and I'm also not able to do them with a mixed client-server role for all the ESPs modules to avoid the endless loop of calls and answers.

You can see that sketch are your own examples, so maybe you can do a quick write with the proper reply sentences you say with .write() directly over these sketch, and for me will be much more easy to understand how I need build the sentences to build calls to upd.write() and packet.write, etc, and where need be placed on the code to avoid the infinite "ping-pong" loop.

Thank you so much!

Ok. I think I have enough success for what I need to do.
My goal is that any ESP have to reply to a multicast call that once processed match to he.
so.. the sketch will be the same on all ESP,
Of course, for me still mostly unknown how the library are working and how to proper use it, and o bunch of other huge lacks of knowledge about how all this is working, but for my needs I think maybe can do the job,
Of course any comment how to better make it or any other suggestion will be more than welcomed.

That's I got for now:

#include <ESP8266WiFi.h>
#include "ESPAsyncUDP.h"

const char* ssid = "SSID";
const char* password = "WIFIKEY";
 

AsyncUDP udp;


void setup()
{
    Serial.begin(115200);
    Serial.println();
    Serial.println();
    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, password);
    if (WiFi.waitForConnectResult() != WL_CONNECTED) {
        Serial.println("WiFi Failed");
        while(1) {
            delay(1000);
        }
    }
     if(udp.listenMulticast(IPAddress(239,1,2,3), 1234)) {
        
        Serial.print("UDP Listening on IP: ");
        Serial.println(WiFi.localIP());
        
        udp.onPacket([](AsyncUDPPacket packet) {
            Serial.print("UDP Packet Type: ");
            Serial.print(packet.isBroadcast()?"Broadcast":packet.isMulticast()?"Multicast":"Unicast");
            Serial.print(", From: ");
            Serial.print(packet.remoteIP());
            Serial.print(":");
            Serial.print(packet.remotePort());
            Serial.print(", To: ");
            Serial.print(packet.localIP());
            Serial.print(":");
            Serial.print(packet.localPort());
            Serial.print(", Length: ");
            Serial.print(packet.length());
            Serial.print(", Data: ");
            Serial.write(packet.data(), packet.length());
            Serial.println();
            if (packet.isMulticast()){
              //Here I have process this call, if match to me need reply, if not, do nothing
              packet.printf("Reply from ESP-1");
              Serial.println("Sended a reply from ESP-1");
            }
       });
        
    }
}

void loop()
{
    delay(5000);
    //Send multicast call
    udp.print("1");
    Serial.println("Sended multicast call from ESP-1");
}

is the sketch the same on both nodes? You can think of the sketch in this way too if it will help:

#include <ESP8266WiFi.h>
#include "ESPAsyncUDP.h"

const char* ssid = "SSID";
const char* password = "WIFIKEY";
 

AsyncUDP udp;

void handlePacket(AsyncUDPPacket packet)
{
     if (packet.isMulticast()){
          //Here I have process this call, if match to me need reply, if not, do nothing
          packet.printf("Reply from ESP-1");
          Serial.println("Sended a reply from ESP-1");
     }
}

void setup()
{
    Serial.begin(115200);
    Serial.println();
    Serial.println();
    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, password);
    if (WiFi.waitForConnectResult() != WL_CONNECTED) {
        Serial.println("WiFi Failed");
        while(1) {
            delay(1000);
        }
    }
    if(udp.listenMulticast(IPAddress(239,1,2,3), 1234)) {
        Serial.print("UDP Listening on IP: ");
        Serial.println(WiFi.localIP());
        udp.onPacket(handlePacket);
    } else {
        Serial.println("UDP Failed");
        while(1) delay(1000);//nothing
    }
}

void loop()
{
    delay(5000);
    //Send multicast call
    udp.print("1");
    Serial.println("Sended multicast call from ESP-1");
}

Sorry about the delay. I'm a few days on holidays and of course disconnected from the net.
Yes, Sure helps. That's the approach for restructuring the code I finded and I'm now start writing the "handlePacket" function that you point above.
I hope to have enough skill and all information needed on handling your AsyncUDP library to complete the code and that it works correctly
In case of any jam I will require your help again.
Thank you so much.
Regards

commented

[STALE_SET] This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs. Thank you for your contributions.

commented

[STALE_DEL] This stale issue has been automatically closed. Thank you for your contributions.