You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
following issue #858, which is still making me struggle, I am now facing the following issue:
If I try to send an UDP packet in Access Point mode, opened after having unsuccesfully tried to connect to some networks, the function endPacket() always fails after updating to 4.1.3 release of Arduino Mbed OS GIGA Boards. The problem persists in release 4.1.5.
A bit of background: in my project, I need to:
try to connect to some WiFi network,
If/when the connection fails, open Access Point and, through a captive portal, ask user to insert SSID and pwd to their WiFi connection (needed on first start and later, in case of credentials changes, for instance),
Connect to the WiFi with the new credentials.
I am attaching a simplified version of my code below, but I guess you can easily build up one on your own.
Many thanks for your contribution!
/*
Adaptation of examples created by Tom Igoe and modified by Karl Söderby
*/
#include <WiFi.h>
#include <WiFiUdp.h>
char ssid[] = "arduinoAP"; // your network SSID (name)
char pass[] = "qwerty123"; // your network password (use for WPA, or use as key for WEP)
#define DBGON // Debug option -serial print
#define DBGONP
#define DBGON_X // Debug option - incl UDP (DNS) packets
// Define UDP settings for DNS
#define UDP_PACKET_SIZE 1024 // UDP packet size time out, preventign too large packet reads
#define DNS_HEADER_SIZE 12 // DNS Header
#define DNS_ANSWER_SIZE 16 // DNS Answer = standard set with Packet Compression
#define DNS_MAX_REQUESTS 32 // trigger first DNS requests, to redirect to own web-page
#define AP_DNS_PORT 53 // local port to listen for UDP packets
#define AP_CHANNEL 5 // AP wifi channel
WiFiUDP udp; // A UDP instance to let us send and receive packets over UDP
IPAddress ap_ip; // Global Acces Point IP adress
int status = WL_IDLE_STATUS;
WiFiServer server(80);
bool AP_DNSRedirect(void)
{
int t = 0; // loop index
int flag = 0; // conditions check
uint16_t packet_size = 0;
uint16_t reply_size = 0;
IPAddress client_ip;
int client_port;
byte packet_buffer[UDP_PACKET_SIZE + DNS_ANSWER_SIZE]; // buffer to hold incoming and outgoing packets
// get packet size, if available
packet_size = udp.parsePacket();
// something went wrong, return with error
if (packet_size > UDP_PACKET_SIZE)
{
Serial.println("DNS INFO: too large packet Error, size " + String(packet_size));
return false;
}
// packet available, read it
if (packet_size > 0)
{
// read packet from client
int plen = udp.read(packet_buffer, packet_size);
if (plen > 0 && plen < UDP_PACKET_SIZE) // just to be sure
{ packet_buffer[plen] = 0;
}
// get client address
client_ip = udp.remoteIP();
client_port = udp.remotePort();
// skip own requests (ntp-pool time request from WiFi module)
if (client_ip != ap_ip)
{
// print debug info
Serial.println("DNS INFO: received " + String(packet_size) + "bytes from " + String(client_ip) + "-" + String(client_port));
Serial.print(" ");
for (t = 0; t < packet_size; ++t) {
Serial.print(String(packet_buffer[t], HEX));
Serial.print(":");
}
Serial.println();
// ---------- BUILD REPLY ON REQUEST ---------- //
// change HEADER
packet_buffer[2] = 0x81; // answare header code
packet_buffer[3] = 0x80; // answare header code
packet_buffer[4] = 0x00; // QDCOUNT = 1 question
packet_buffer[5] = 0x01; // QDCOUNT = 1 question
packet_buffer[6] = 0x00; // ANCOUNT = 1 answer
packet_buffer[7] = 0x01; // ANCOUNT = 1 answer
packet_buffer[8] = 0x00; // NSCOUNT / ignore
packet_buffer[9] = 0x00; // NSCOUNT / ignore
packet_buffer[10] = 0x00; // ARCOUNT / ignore
packet_buffer[11] = 0x00; // ARCOUNT / ignore
// retain end of question plus Qtype and Qclass 5 octets
for (reply_size = 12; packet_buffer[reply_size] != 0; reply_size++);
reply_size += 5;
// add answer to reply
packet_buffer[reply_size++] = 0xc0; // pointer to pos 12 : NAME Labels
packet_buffer[reply_size++] = 0x0c; // pointer to pos 12 : NAME Labels
packet_buffer[reply_size++] = 0x00; // TYPE
packet_buffer[reply_size++] = 0x01; // TYPE
packet_buffer[reply_size++] = 0x00; // CLASS
packet_buffer[reply_size++] = 0x01; // CLASS
packet_buffer[reply_size++] = 0x00; // TTL
packet_buffer[reply_size++] = 0x00; // TTL
packet_buffer[reply_size++] = 0x18; // TLL 2 days
packet_buffer[reply_size++] = 0x4c; // TLL 2 days
packet_buffer[reply_size++] = 0x00; // RDLENGTH = 4
packet_buffer[reply_size++] = 0x04; // RDLENGTH = 4
packet_buffer[reply_size++] = ap_ip[0]; // AP ip address
packet_buffer[reply_size++] = ap_ip[1]; // AP ip address
packet_buffer[reply_size++] = ap_ip[2]; // AP ip address
packet_buffer[reply_size++] = ap_ip[3]; // AP ip address
// print debug info
Serial.println("DNS INFO: reply " + String(reply_size) + " bytes from " + String(ap_ip) + "-" + String(AP_DNS_PORT));
Serial.print(" ");
for (t = 0; t < reply_size; ++t) {
Serial.print(String(packet_buffer[t], HEX));
Serial.print(":");
}
Serial.println();
Serial.println(" " + String((char*)packet_buffer));
// ---------- START SENDING REPLY ---------- //
flag = udp.beginPacket(client_ip, client_port);
Serial.println("DNS INFO: beginPacket() -> " + String(flag));
udp.write(packet_buffer, reply_size);
flag = udp.endPacket();
Serial.println("DNS INFO: endPacket() -> " + String(flag));
if (flag <= 0)
{
Serial.println("DNS ERROR: endPacket() Failed.");
return false;
}
}
}
return true;
}
void wifiCleanup(void)
{
udp.stop(); // should be ok even on non-initialized UDP
delay(2);
WiFi.disconnect();
WiFi.end();
delay(20);
// WiFi = WiFiClass(WiFiInterface::get_default_instance());
}
void printWiFiStatus(void)
{
Serial.println("-- WIFI INFO ----------------------------");
Serial.print (" SSID: "); Serial.println(WiFi.SSID());
Serial.print (" IP addr: "); Serial.println(WiFi.localIP());
Serial.print (" IP gatew: "); Serial.println(WiFi.gatewayIP());
Serial.print (" RSSI: "); Serial.print(WiFi.RSSI()); Serial.println("dBm");
Serial.println("-----------------------------------------");
}
void setup() {
//Initialize serial and wait for port to open:
Serial.begin(115200);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial.println("Access Point Web Server");
// check for the WiFi module:
if (WiFi.status() == WL_NO_MODULE) {
Serial.println("Communication with WiFi module failed!");
// don't continue
while (true)
;
}
// start the web server on port 80
server.begin();
// ----- TRY TO CONNECT TO SOME NETWORK... ----- //
Serial.println("Connecting to inexistent network...");
status = WiFi.begin("unkwnown", "password1");
Serial.print("WIFI STATUS: "); Serial.println(status);
printWiFiStatus();
// delay(5000);
wifiCleanup();
Serial.print("WIFI STATUS: "); Serial.println(WiFi.status());
printWiFiStatus();
// connection failed, now open access point
// ----- OPEN ACCESS POINT ----- //
// print the network name (SSID);
Serial.print("Creating access point named: ");
Serial.println(ssid);
ap_ip = IPAddress((char)random(11, 172), (char)random(0, 255), (char)random(0, 255), 0x01); // Generate random IP adress in Private IP range
WiFi.config(ap_ip, ap_ip, ap_ip, IPAddress(255, 255, 255, 0)); // Setup config
// Create open network. Change this line if you want to create an WEP network:
status = WiFi.beginAP(ssid, pass);
if (status != WL_AP_LISTENING) {
Serial.println("Creating access point failed");
// don't continue
while (true);
}
// wait some seconds for connection:
delay(6000);
// you're connected now, so print out the status
printWiFiStatus();
int udp_err = udp.begin(AP_DNS_PORT);
Serial.println("UDP begin(" + String(AP_DNS_PORT) + "): " + String((int)udp_err));
Serial.println("Setup completed. Ready for connection.");
}
void loop() {
// compare the previous status to the current status
if (status != WiFi.status()) {
// it has changed update the variable
status = WiFi.status();
if (status == WL_AP_CONNECTED) {
// a device has connected to the AP
Serial.println("Device connected to AP");
} else {
// a device has disconnected from the AP, and we are back in listening mode
Serial.println("Device disconnected from AP");
}
}
// use UDP to hijack client to our captive portal
AP_DNSRedirect();
// listen for incoming clients
WiFiClient client = server.available();
if (client) { // if you get a client,
Serial.println("new client"); // print a message out the serial port
String currentLine = ""; // make a String to hold incoming data from the client
while (client.connected()) { // loop while the client's connected
delayMicroseconds(10); // This is required for the Arduino Nano RP2040 Connect - otherwise it will loop so fast that SPI will never be served.
if (client.available()) { // if there are bytes to read from the client,
char c = client.read(); // read a byte, then
Serial.write(c); // print it out the serial monitor
if (c == '\n') { // if the byte is a newline character
// if the current line is blank, you got two newline characters in a row.
// that's the end of the client HTTP request, so send a response:
if (currentLine.length() == 0) {
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client knows what's coming, then a blank line:
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println();
// the content of the HTTP response follows the header:
client.print("Click <a href=\"/HR\">here</a> turn the RED LED on<br>");
client.print("Click <a href=\"/LR\">here</a> turn the RED LED off<br>");
client.print("Click <a href=\"/HG\">here</a> turn the GREEN LED ON<br>");
client.print("Click <a href=\"/LG\">here</a> turn the GREEN LED off<br>");
client.print("Click <a href=\"/BH\">here</a> turn the BLUE LED on<br>");
client.print("Click <a href=\"/BL\">here</a> turn the BLUE LED off<br>");
// The HTTP response ends with another blank line:
client.println();
// break out of the while loop:
break;
} else { // if you got a newline, then clear currentLine:
currentLine = "";
}
} else if (c != '\r') { // if you got anything else but a carriage return character,
currentLine += c; // add it to the end of the currentLine
}
// Check to see if the client request (turns ON/OFF the different LEDs)
if (currentLine.endsWith("GET /HR")) {
digitalWrite(LED_RED, LOW);
}
if (currentLine.endsWith("GET /LR")) {
digitalWrite(LED_RED, HIGH);
}
if (currentLine.endsWith("GET /HG")) {
digitalWrite(LED_GREEN, LOW);
}
if (currentLine.endsWith("GET /LG")) {
digitalWrite(LED_GREEN, HIGH);
}
if (currentLine.endsWith("GET /BH")) {
digitalWrite(LED_BLUE, LOW);
}
if (currentLine.endsWith("GET /BL")) {
digitalWrite(LED_BLUE, HIGH);
}
}
}
// close the connection:
client.stop();
Serial.println("client disconnected");
}
}
The text was updated successfully, but these errors were encountered:
I was debugging my code and discovered that even on MBED OS Release 4.1.1 WiFiUDP::endPacket() fails if it was preceded by some attempts to connect with a wrong password to an exisiting network. If I try to connect to some networks that does not exist, on the other hand, everything works fine.
I was tempted to open a new issue and link it here, but I guess it can be treated as a single issue.
Dear developers,
following issue #858, which is still making me struggle, I am now facing the following issue:
If I try to send an UDP packet in Access Point mode, opened after having unsuccesfully tried to connect to some networks, the function
endPacket()
always fails after updating to 4.1.3 release of Arduino Mbed OS GIGA Boards. The problem persists in release 4.1.5.A bit of background: in my project, I need to:
I am attaching a simplified version of my code below, but I guess you can easily build up one on your own.
Many thanks for your contribution!
The text was updated successfully, but these errors were encountered: