Skip to content

UDP Multicast does not continuously receive replies! #2340

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
iVisionary opened this issue Jul 29, 2016 · 12 comments
Closed

UDP Multicast does not continuously receive replies! #2340

iVisionary opened this issue Jul 29, 2016 · 12 comments
Assignees
Labels
type: troubleshooting waiting for feedback Waiting on additional info. If it's not received, the issue may be closed.

Comments

@iVisionary
Copy link

Description

Problem description
Hello everyone. I have tried these sketches below to send multicast messages to all nodes connected to this sender and receive an acknowledgement back to the sender every time the message received. The problem is the acknowledgement received once or twice only. I found that the reply is not sent from the receiver. When I reset the ESP8266 it will send the reply once or twice then stop sending. A screen shoot is attached. Please your advice on this issue.
IDE version 1.6.9

Sketch_Multicast server

#include <ESP8266WiFi.h>
#include <WiFiUDP.h>

int status = WL_IDLE_STATUS;
const char* ssid = "UDP";  //  your network SSID (name)
const char* pass = "udptest1";       // your network password

unsigned int localPort = 2390;      // local port to listen for UDP packets
char packetBuffer[10]; //buffer to hold incoming and outgoing packets

// A UDP instance to let us send and receive packets over UDP
WiFiUDP Udp_Send;
WiFiUDP Udp_Rec;

// Multicast declarations
IPAddress ipMulti(192,168,4,255);
unsigned int portMulti = 23;      // local port to listen on

void setup()
{
  // Open serial communications and wait for port to open:
  Serial.begin(115200);

  WiFi.softAP(ssid, pass);
  IPAddress myIP = WiFi.softAPIP();
  Serial.println(" AP IP Address: ");
  Serial.print(myIP);

  Serial.println();
//printWifiStatus();

  Serial.print("Udp Multicast server started at : ");
  Serial.print(ipMulti);
  Serial.print(":");
  Serial.println(localPort);
  //Udp_Rec.beginMulticast(myIP,  ipMulti, portMulti);
  Udp_Rec.begin(localPort); 
}

void loop()
{
  //Udp_Rec.begin(localPort);
  int noBytes = Udp_Rec.parsePacket();
  if ( noBytes ) {
    Serial.print(millis() / 1000);
    Serial.print(":Packet of ");
    Serial.print(noBytes);
    Serial.print(" received from ");
    Serial.print(Udp_Rec.remoteIP());
    Serial.print(":");
    Serial.println(Udp_Rec.remotePort());
    // We've received a packet, read the data from it
    Udp_Rec.read(packetBuffer,noBytes); // read the packet into the buffer

    // display the packet contents
    for (int i=1;i<=noBytes;i++){
      Serial.print(packetBuffer[i-1]);
      if (i % 32 == 0){
        Serial.println();
      }
      else Serial.print(' ');
    } // end for
    Serial.println();
    //fncUdpSend();
  } // end if

  delay(1000);
  fncUdpSend();
}

void fncUdpSend()
{
  strcpy(packetBuffer, "HELLO!"); 
  Udp_Send.beginPacket(ipMulti, localPort);
  Udp_Send.write(packetBuffer, sizeof(packetBuffer));
  Udp_Send.endPacket();
  //Udp_Send.stop();
}

Sketch_Receiver

#include <ESP8266WiFi.h>
#include <WiFiUDP.h>

int status = WL_IDLE_STATUS;
const char* ssid = "UDP";  //  your network SSID (name)
const char* pass = "udptest1";       // your network password

unsigned int localPort = 2390;      // local port to listen for UDP packets

//unsigned int ReplyPort = 2390;
IPAddress ReplyIP(192,168,4,1);
char ReplyBuffer[10] = "OK!";

char packetBuffer[10]; //buffer to hold incoming and outgoing packets

// A UDP instance to let us send and receive packets over UDP
WiFiUDP Udp_r;      // Receive 

void setup()
{
  // Open serial communications and wait for port to open:
  Serial.begin(115200);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }

  // prepare GPIO2
  pinMode(2, OUTPUT);
  digitalWrite(2, 1);

  // setting up Station AP
  WiFi.begin(ssid, pass);

  // Wait for connect to AP
  Serial.print("[Connecting]");
  Serial.print(ssid);
  int tries=0;
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
    tries++;
    if (tries > 30){
      break;
    }
  }
  Serial.println();
  IPAddress ip(192,168,4,10);        // static IP 
  IPAddress gateway(192,168,4,12);
  IPAddress subnet(255,255,255,0);
  WiFi.config(ip,gateway,subnet);      // set a static ip to the WiFi 

//printWifiStatus();

  Serial.println("Connected to wifi");
  Serial.print("Udp server started at port ");
  Serial.print(WiFi.localIP());
  Serial.print(" : ");
  Serial.println(localPort);
  Udp_r.begin(localPort);
}
int val = 1;
void loop()
{
  int noBytes = Udp_r.parsePacket();
  if ( noBytes ) {
    Serial.print(millis() / 1000);
    Serial.print(":Packet of ");
    Serial.print(noBytes);
    Serial.print(" received from ");
    Serial.print(Udp_r.remoteIP());
    ReplyIP = Udp_r.remoteIP();
    Serial.print(":");
    Serial.println(Udp_r.remotePort());
    // We've received a packet, read the data from it
    Udp_r.read(packetBuffer,noBytes); // read the packet into the buffer

    // display the packet contents
    for (int i=1;i<=noBytes;i++){
      Serial.print(packetBuffer[i-1]);
      if (i % 32 == 0){
        Serial.println();
      }
      else Serial.print(' ');
    } // end for
    Serial.println();
    val++;
    if(val % 2){
      digitalWrite(2, HIGH);
    }
    else 
    digitalWrite(2, LOW);
    delay(1000);
    //Udp_r.flush();
    fncUdpSend();
  } // end if
}

void fncUdpSend()
{

  WiFiUDP Udp_s;
  //strcpy(ReplyBuffer, "HELLO!");
  Udp_s.beginPacket(ReplyIP, localPort);
  Udp_s.write(ReplyBuffer, sizeof(ReplyBuffer));
  Udp_s.endPacket();
}

### Debug Messages
![untitled](https://cloud.githubusercontent.com/assets/19645378/17241493/9c740db6-557a-11e6-9dda-a20024a8828e.jpg)

messages here



@me-no-dev
Copy link
Collaborator

UDP is not a guaranteed delivery protocol ;) you might get the packet, but you might also miss it if you are doing something else. TCP should be used if you want to get all packets

@iVisionary
Copy link
Author

Yeah, but the question is why the delivery is okay in one direction; i.e. only the mutlicast messages are received, but not okay in the reply? and It's not that necessary to receive every packet sent but at least it should receive some packets continuously as it's written to do so. Regarding the TCP, I think it does not support multicasting I'm not an expert on this correct me if i'm wrong :)

@me-no-dev
Copy link
Collaborator

code above is unicast, not multicast.
and the server is attempting to send broadcast.
You delay 1 second in both loops. Why? You will get your messages discarded if other UDP messages arrive (from other places)�

@mkeyno
Copy link

mkeyno commented Jul 29, 2016

@me-no-dev is it good idea to make handler just like the `server.handleClient();`` so can manage the udp packages, or even why you don't wrap it inside your async handler repo

@me-no-dev
Copy link
Collaborator

There is this thing available but requires git version of this repository

@iVisionary
Copy link
Author

@me-no-dev the mulicast is by calling Udp_Rec.beginMulticast(myIP, ipMulti, portMulti); in stead of this Udp_Rec.begin(localPort); I've already done that but ended up with the same results. The delay in the 1st sketch is what I want the sender to do; keep sending a multicast message every second. In the receiver side the delay is just doesn't make any difference because I've already tried without delay gave the same result.
The Issue is that the reply message is sent 2 - 3 times and then no reply will be transmitted while continuously receiving the multicast messages. Any idea ?

@me-no-dev
Copy link
Collaborator

correct way to deal with delayed sending of packets is to check in the loop if that time has pass and act if so. Delaying there does not let you handle any incoming packet while waiting which can very well lead to missed packets.

@iVisionary
Copy link
Author

iVisionary commented Aug 1, 2016

Thank you @me-no-dev for your reply. I will deal with the delay in a different way as your note does make sense in the sender side. But again the reply message in the receiver side is not transmitted more that 2-3 times. I have checked that by checking the on board LED
if(Udp_s.endPacket()){
digitalWrite(2, 0);
delay(200);
digitalWrite(2, 1);
}

@electron1979
Copy link

electron1979 commented Sep 29, 2016

Hi all.
If I use system_deep_sleep, it doesn't sleep and no UDP is sent? It does seem to reset.
If I use ESP.deepSleep, it sleeps, gets the time, but no UDP data is sent?
Either way, UDP is not sent even once (before deep sleep).

If I don't use any deep-sleep, everything works.
Any ideas?

I'm not ready to set-up a MTTQ broker.
MTTQ seems more common and I haven't seen any problems with deep sleep.

IDE 1.6.10, esptool.exe 0.4.9, Win10 x64

http://www.esp8266.com/viewtopic.php?p=55867#p55867

//extern "C" { // For 'system_deep_sleep()'
//#include "user_interface.h"
//}

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

#include "TimeClient.h"
float utcOffset = 9.5; // enter your UTC
TimeClient timeClient(utcOffset);

const char* ssid     = "SSID";
const char* password = "Password";
IPAddress ipBroadCast(192, 168, 1, 200); // Destination IP
const unsigned int udpRemotePort = 8889; // Destination Port

const int sleepTimeS = 3; // Deep sleep time (s)

const int UDP_PACKET_SIZE = 10; // excluding NL character
char udpBuffer[UDP_PACKET_SIZE];
WiFiUDP udp; // setup UDP object


//////////////// SETUP ///////////////
void setup() {
  delay(500);
  Serial.begin(57600);
  delay(100);
// We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid); 
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
      delay(500);
      Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected"); 
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  Serial.print("Destination IP address: ");
  Serial.println(ipBroadCast);
  Serial.print("Port: ");
  Serial.println(udpRemotePort);
  Serial.println("Starting UDP");

}

void loop() { 

  timeClient.updateTime();
  //String time = timeClient.getFormattedTime();

  strcpy(udpBuffer, "abcdefghij"); // Debug message
  udp.beginPacket(ipBroadCast, udpRemotePort);
  delay(10);
  udp.write(udpBuffer, sizeof(udpBuffer));
  delay(10);
  udp.endPacket();
  udp.flush(); // not required (doesn't help)

  Serial.print("Sent: ");
  Serial.println(udpBuffer);

  //// SLEEP ////
  Serial.println("Entering sleep mode...");
  Serial.println(""); 
  //WiFi.forceSleepBegin();
  //ESP.deepSleep(sleepTimeS * 1000*1000, WAKE_RF_DEFAULT); // or WAKE_RFCAL or WAKE_NO_RFCAL or WAKE_RF_DISABLED or WAKE_RF_DEFAULT
  //ESP.deepSleep(3 * 1000*1000);
  //system_deep_sleep(3 * 1000*1000);
  Serial.println("Exiting sleep mode...");

  delay(1*1000); 
} 

@devyte
Copy link
Collaborator

devyte commented Oct 14, 2017

@iVisionary is this issue still valid in latest git? In PR #3362 (lwip2)?

@devyte devyte added the waiting for feedback Waiting on additional info. If it's not received, the issue may be closed. label Oct 14, 2017
@d-a-v
Copy link
Collaborator

d-a-v commented Nov 18, 2017

Worth a try with lwip2.
I don't really get why the (referenced above) endPacket() problem is solved by lwip2, because it was mainly TCP which was broken in lwip1.4.
UDP seems to behave better too, so worth a try.

@d-a-v
Copy link
Collaborator

d-a-v commented Nov 9, 2020

Closing due to age, lack of answer, and problem probably solved due to numerous fixes in UDP and multicast.
Feel free to open a new issue if is is not solved.

@d-a-v d-a-v closed this as completed Nov 9, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: troubleshooting waiting for feedback Waiting on additional info. If it's not received, the issue may be closed.
Projects
None yet
Development

No branches or pull requests

7 participants