Closed fredlcore closed 3 years ago
ArduinoMDNS states that
any Arduino core and networking library that supports the new virtual UDP::beginMulticast(...) method
would be working. Could that be the root of the problem?
You're absolutely right. This function is not implemented and from the inner class UDP returns always 0. I don't know what should it look like, nor what should it do. Please hold on, I'll look at it.
That would be awesome, thanks!
I am sorry, I haven't looked at it yet. It requires some investigation what actually the multicast is and how could I test it. I am unable to find an example for testing the multicast. Do you have any?
No worries, I'm glad you're looking into it! As for what Multicast is, here are a few links with examples that might be helpful (if a destination IP is used, it has to be of the multicast address range, i.e. 224.0.0.0 through 239.255.255.255. ArduinMDNS uses 224.0.0.251):
Arduino UDP Multicast send/receive: https://tkkrlab.nl/wiki/Arduino_UDP_multicast Multicast tutorial: https://community.particle.io/t/multicast-udp-tutorial/19900 Sender and listener for Linux written in C++: https://gist.github.com/hostilefork/f7cae3dc33e7416f2dd25a402857b6c6
Other than that, this is the beginMulticast-code from EthernetUdp.cpp (the "makesocket" section is releant here, I guess, and most of it is calculating the MAC address based on the Multicast IP address):
// multicast version to set fields before open thd
uint8_t EthernetClass::socketBeginMulticast(uint8_t protocol, IPAddress ip, uint16_t port)
{
uint8_t s, status[MAX_SOCK_NUM], chip, maxindex=MAX_SOCK_NUM;
// first check hardware compatibility
chip = W5100.getChip();
if (!chip) return MAX_SOCK_NUM; // immediate error if no hardware detected
#if MAX_SOCK_NUM > 4
if (chip == 51) maxindex = 4; // W5100 chip never supports more than 4 sockets
#endif
//Serial.printf("W5000socket begin, protocol=%d, port=%d\n", protocol, port);
SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
// look at all the hardware sockets, use any that are closed (unused)
for (s=0; s < maxindex; s++) {
status[s] = W5100.readSnSR(s);
if (status[s] == SnSR::CLOSED) goto makesocket;
}
//Serial.printf("W5000socket step2\n");
// as a last resort, forcibly close any already closing
for (s=0; s < maxindex; s++) {
uint8_t stat = status[s];
if (stat == SnSR::LAST_ACK) goto closemakesocket;
if (stat == SnSR::TIME_WAIT) goto closemakesocket;
if (stat == SnSR::FIN_WAIT) goto closemakesocket;
if (stat == SnSR::CLOSING) goto closemakesocket;
}
#if 0
Serial.printf("W5000socket step3\n");
// next, use any that are effectively closed
for (s=0; s < MAX_SOCK_NUM; s++) {
uint8_t stat = status[s];
// TODO: this also needs to check if no more data
if (stat == SnSR::CLOSE_WAIT) goto closemakesocket;
}
#endif
SPI.endTransaction();
return MAX_SOCK_NUM; // all sockets are in use
closemakesocket:
//Serial.printf("W5000socket close\n");
W5100.execCmdSn(s, Sock_CLOSE);
makesocket:
//Serial.printf("W5000socket %d\n", s);
EthernetServer::server_port[s] = 0;
delayMicroseconds(250); // TODO: is this needed??
W5100.writeSnMR(s, protocol);
W5100.writeSnIR(s, 0xFF);
if (port > 0) {
W5100.writeSnPORT(s, port);
} else {
// if don't set the source port, set local_port number.
if (++local_port < 49152) local_port = 49152;
W5100.writeSnPORT(s, local_port);
}
// Calculate MAC address from Multicast IP Address
byte mac[] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0x00 };
mac[3] = ip[1] & 0x7F;
mac[4] = ip[2];
mac[5] = ip[3];
W5100.writeSnDIPR(s, ip.raw_address()); //239.255.0.1
W5100.writeSnDPORT(s, port);
W5100.writeSnDHAR(s, mac);
W5100.execCmdSn(s, Sock_OPEN);
state[s].RX_RSR = 0;
state[s].RX_RD = W5100.readSnRX_RD(s); // always zero?
state[s].RX_inc = 0;
state[s].TX_FSR = 0;
//Serial.printf("W5000socket prot=%d, RX_RD=%d\n", W5100.readSnMR(s), state[s].RX_RD);
SPI.endTransaction();
return s;
}
Jiri, it is used the same way as UDP.begin(). Only send WiFiSpiUdp.beginMulticast to WiFiUdp.beginMulticast of the ESP8266WiFi library.
@fredlcore and Juraj: thank you so much. I hope now I have all the information needed to implement it.
You're most welcome, thank you for your effort, and thanks, @jandrassy for this really helpful information!
~~Hi, I realized that on my network, I am not able to use a multicast. It may be an issue of my router (TPLink Archer C5) or whatever. No matter if I try to transmit wired or wireless. Do you have any ideas? I am not able to test UDP Multicast now.~~
Edit: it is not an issue with a router but with the VirtualBox, namely its ethernet adapter. Eventually, I tried it on another PC and it runs. (https://www.virtualbox.org/ticket/8698)
I created new branch here and in the WiFiSpiESP repository named UDP_Multicast. @fredlcore please check them out and test if the library works for you. I also added two examples (multicast transmit and receive).
Great! I was just about to give up when the errors came again until I ran the test case above again and it notified me that also the ESP part had changed. So once I flashed the ESP with the new version, it works like charm, thanks so much :)!
Will you merge this directly into the master branch or should I refer people to this branch instead?
Thanks for testing, I'll merge it to the master.
Closed via https://github.com/JiriBilek/WiFiSpi/pull/29
I'm trying to get the ArduinoMDNS example for registering a service working with WiFiSpi. The original sketch can be found here: https://github.com/arduino-libraries/ArduinoMDNS/blob/master/examples/Ethernet/RegisteringServices/RegisteringServices.ino I have adapted it to work with WiFiSpi and WiFiSpiUdp and it compiles fine, but after the
mdns.addServiceRecord("Arduino mDNS Webserver Example._http", 80, MDNSServiceTCP);
line, the debug output of the Arduino (Due) is filled with these lines:The sketch seems to stay in some kind of infinite loop repeating these messages.
Is WiFiSpiUdp (significantly) different from EthernetUDP, so that the mDNS library cannot be used with WiFiSpi? Or is this (hopefully) just a misconfiguration or bug that can be fixed?
Here's the test case: