I am connecting 4 nodemcu (esp8266). 1 esp8266 is used as access point and others are connected to it.
When I send UDP packets as a broadcast message to all the esp8266 via with esp8266 as access point it is not recieved by the others however when I use a home router or even by mobile hotspot as access point, the broadcast messages are received by the other esp8266.
Also, I have posted here a part of my code that is used for UDP so there may be some variables that you will see as undeclared but they are originally declared and the code is working when I connect it with Access Point that is not esp8266
Code For Access Point:
#include
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.print("Setting soft-AP ... ");
boolean result = WiFi.softAP("ssid", "password123456");
if(result == true)
{
Serial.println("Ready");
}
else
{
Serial.println("Failed!");
}
}
void loop()
{
Serial.printf("Stations connected = %d\n",
WiFi.softAPgetStationNum());
delay(3000);
}
Code for sending UPD packet as broadcast:
unsigned int localPort = 2000;
IPAddress SendIP(192,168,43,255);
setup()
{
udp.begin(localPort);
Serial.print("Local port: ");
Serial.println(udp.localPort());
}
loop()
{
udp.beginPacket(SendIP, 2000);
udp.write("p");
udp.endPacket();
}
Code for Recieving UDP packets:
void loop()
{
int packetSize = udp.parsePacket();
if(packetSize)
{
udp.read(packetBuffer,UDP_TX_PACKET_MAX_SIZE);
p = packetBuffer[0];
Serial.println(p);
function();
}
Please tell me whats the problem with using esp8266 as access point to send UDP packets.
And if esp8266 can not be used please tell me any other chip that can do the work, I want to make a portable system so I cannot use the router.
The default IP address of ESP8266 router in AP mode is 192.168.244.1.
Try to change sending address to 192.168.244.255.
Related
I am trying to create a small project on arduino (WeMos D1 mini). It is to be based on the communication of several devices with a computer using the MQTT protocol.
The protocol itself works great on arduino. I wrote a program that works as expected, at least at this stage of the project.
The problem is that it works fine on a single arduino. I need to create a network of devices.
Is it possible to execute the sequence on several devices communicating via MQTT?
Example: Own MQTT Broker on Raspberry Pi. Three Arduino (id: 001; 002; 003) with the same program. Is the sequence possible: I am sending a startup message from the computer to Arduino 001. The device does some work, then sends a log to the computer and a message to Arduino 002. Device 002 does the job, then sends a log to the computer and a message to Arduino 003. Device 003 does the job , then sends the log to the computer and completes the sequence.
Message from computer to Arduino 001 is sent to Topic device / 001, to Arduino 002 it is sent to Topic device / 002 and similarly to Arduino 003 it is sent to Topic device / 003.
Today I have a problem because when I run all Arduino's at the same time, only one is active on the network. the other two are unresponsive although the Broker receives the information. Why ?
So, after lond descriptions time for code:
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <PubSubClientTools.h>
#include <Thread.h>
#include <ThreadController.h>
#define WIFI_SSID "MyNetwork"
#define WIFI_PASS "123456789"
#define serial 9600
#define MQTT_SERVER "192.168.8.107"
#define MQTT_PORT 1883
#define id_dev "001"
WiFiClient espClient;
PubSubClient client(MQTT_SERVER, MQTT_PORT, espClient);
PubSubClientTools mqtt(client);
ThreadController threadControl = ThreadController();
Thread thread = Thread();
int value = 0;
const String s = "";
String service = "service";
String main_name = "test";
String sub_main_name = "test";
String info_name = "test";
String sub_info_name = "test";
void setup() {
Serial.begin(serial);
Serial.println("-| WiFi Connection |--------------------------------");
setup_wifi();
Serial.println("-| MQTT Connection |--------------------------------");
Serial.print(s+"Connecting to MQTT: "+MQTT_SERVER+" ... ");
if (client.connect("ESP8266Client")) {
Serial.println("connected");
mqtt.subscribe(service+"/"+id_dev, topic_service);
mqtt.subscribe(main_name, topic_main_name);
mqtt.subscribe(info_name, topic_info_name);
} else {
Serial.println(s+"failed, rc="+client.state());
}
// Enable Thread
// thread.onRun(publisher);
thread.setInterval(2000);
threadControl.add(&thread);
Serial.println("----------------------------------------------------");
Serial.println();
}
void loop() {
client.loop();
threadControl.run();
}
void setup_wifi() {
Serial.print("Connecting to ");
Serial.println(WIFI_SSID);
WiFi.begin(WIFI_SSID, WIFI_PASS);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
void publisher() {
++value;
mqtt.publish("test/001", s+"Hello World! - No. "+value);
}
void topic_service(String topic, String message) {
Serial.println(s+"Message arrived in function 1 ["+topic+"] "+message);
sub_main_name = message;
subscription(sub_main_name);
}
void topic_main_name(String topic, String message) {
Serial.println(s+"Message arrived in function 2 ["+topic+"] "+message);
if (message == "111") {
Serial.println("Is OK!");
String message_sent = "111";
mqtt.publish(sub_main_name+"/002", message_sent);
} else {
Serial.println("Something wrong!");
}
}
void topic_info_name(String topic, String message) {
Serial.println(s+"Message arrived in function 3 ["+topic+"] "+message);
sub_info_name = message;
}
void subscription(String wiadomosc){
if(main_name != wiadomosc){
Serial.println("main_name: " + main_name + " | sub_main_name: " + sub_main_name +" <- for change");
main_name = sub_main_name+"/"+id_dev;
info_name = sub_main_name+"/"+id_dev+"/i";
mqtt.subscribe(main_name, topic_main_name);
mqtt.subscribe(info_name, topic_info_name);
}
}
//----------------------------------------------------
The same code will be uploaded to all devices, diferent will be only ID (id_dev). This is a simple version of my program but it still not working well. On one device is ok but if I run two or more... only lastone is active. The rest are dosn't work (are not visible in network).
I need help getting a network of these devices up and running and communicating between them.
I checked on 2 devices logged in at the same time.
ID 001 (Serial Monitor Tool):
-| WiFi Connection |--------------------------------
Connecting to LinkHome
.......
WiFi connected
IP address: 192.168.8.132
Mac address: 84:F3:EB:0C:42:5E
-| MQTT Connection |--------------------------------
Connecting to MQTT: 192.168.8.107 ... connected
----------------------------------------------------
ID 002 (Serial Monitor Tool):
-| WiFi Connection |--------------------------------
Connecting to LinkHome
.......
WiFi connected
IP address: 192.168.8.123
Mac address: 84:F3:EB:0C:42:55
-| MQTT Connection |--------------------------------
Connecting to MQTT: 192.168.8.107 ... connected
----------------------------------------------------
(log from broker):
1660763173: New connection from 192.168.8.123:63287 on port 1883.
1660763173: New client connected from 192.168.8.123:63287 as ESP8266Client (p2, c1, k15).
1660763213: New connection from 192.168.8.132:51163 on port 1883.
1660763213: Client ESP8266Client already connected, closing old connection.
1660763213: New client connected from 192.168.8.132:51163 as ESP8266Client (p2, c1, k15).
There seems to be a problem in the log file. Two devices named ESP8266Client.
How can I change the device name?
Ok, I found a solution. It was easier than I thought. By the way, I will also be able to change hostnames.
To change the hostname I added three lines:
#define id_dev "002"
String newHostname = "client_"+String(id_dev); // for change the hostname
...
void setup_wifi() {
WiFi.mode(WIFI_STA); // for change the hostname
WiFi.hostname(newHostname); // for change the hostname
Serial.print("Connecting to ");
Serial.println(WIFI_SSID);
WiFi.begin(WIFI_SSID, WIFI_PASS);
...
To change mosquitto client name: I change the name in line:
...
Serial.print(s+"Connecting to MQTT: "+MQTT_SERVER+" ... ");
if (client.connect("dev_001")) {
Serial.println("connected");
...
Thanks for the hint with the log file, I admit I didn't think about it.
I searched how to configure a DHCP server on ESP32 Arduino to distribute addresses for clients that connect to my ESP32 access point, but unfortunately I did not get any source code for that.
Any help?
As long as you use WiFi.softAP(), you do not need to explicitly configure a DHCP server on the ESP32. It will happen automatically - the library looks after it for you.
Here is a minimal example, where - in addition to setting the ESP32 up as an access point - a TCP server is also started on port 80.
WiFiServer server(80);
static const char *ap_ssid = "ESP32-001";
static const char *ap_pass = "temp_pass";
void setup() {
Serial.begin(115200);
WiFi.softAP(ap_ssid, ap_pass);
Serial.print("Access point running. IP address: ");
Serial.print(WiFi.softAPIP());
Serial.println("");
server.begin();
}
void loop() {
WiFiClient client = server.available();
if (client) {
String client_ip = client.remoteIP().toString();
Serial.print("Client connected. IP address = ");
Serial.print(client_ip);
Serial.println("");
client.println("Hello ...");
client.stop();
}
}
I have attached the serial output in a screenshot below. Notice the
dhcps: send_offer>>udp_sendto result 0
message.
I have a Raspberry Pi 3 Model B with ioBroker (Raspbian light Stretch) as an MQTT broker and Wemos D1 ESP 8266 with a test script. Both devices are connected to the network via Wi-Fi.
Good news:
1) I can send the MQTT signal from the phone (myMQTT apps) and it will be displayed in the ioBroker logs (the phone is connected to Wi-Fi, MicroTik).
I can send an MQTT signal from my laptop (connected to Wi-Fi or ethernet).
I can send a successful MQTT signal from a Debian virtual server (on vmware).
2) Wemos D1 successfully connects to the test server test.mosquitto.org.
The bad news:
Wemos D1 does not want to connect to ioBroker on the local network and reports the error "Attempting MQTT connection ... failed, rc = -2 try again in 5 seconds".
Why all devices except Wemos D1 ESP 8266 successfully connect to mqtt broker?
Could it be the case in the firewall?
Tell me, please, what should I do to solve this problem.
/*
Basic ESP8266 MQTT example
This sketch demonstrates the capabilities of the pubsub library in combination
with the ESP8266 board/library.
It connects to an MQTT server then:
- publishes "hello world" to the topic "outTopic" every two seconds
- subscribes to the topic "inTopic", printing out any messages
it receives. NB - it assumes the received payloads are strings not binary
- If the first character of the topic "inTopic" is an 1, switch ON the ESP Led,
else switch it off
It will reconnect to the server if the connection is lost using a blocking
reconnect function. See the 'mqtt_reconnect_nonblocking' example for how to
achieve the same result without blocking the main loop.
To install the ESP8266 board, (using Arduino 1.6.4+):
- Add the following 3rd party board manager under "File -> Preferences -> Additional Boards Manager URLs":
http://arduino.esp8266.com/stable/package_esp8266com_index.json
- Open the "Tools -> Board -> Board Manager" and click install for the ESP8266"
- Select your ESP8266 in "Tools -> Board"
*/
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
// Update these with values suitable for your network.
const char* ssid = "XXX";
const char* password = "XXX";
const char* mqtt_server = "test.mosquitto.org";
WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];
int value = 0;
void setup_wifi() {
delay(5000);
// We start by connecting to a WiFi network
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.mode (WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print(".");
}
randomSeed(micros());
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.println();
// Switch on the LED if an 1 was received as first character
if ((char)payload[0] == '1') {
digitalWrite(BUILTIN_LED, LOW); // Turn the LED on (Note that LOW is the voltage level
// but actually the LED is on; this is because
// it is active low on the ESP-01)
} else {
digitalWrite(BUILTIN_LED, HIGH); // Turn the LED off by making the voltage HIGH
}
}
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Create a random client ID
String clientId = "ESP8266Client-";
clientId += String(random(0xffff), HEX);
// Attempt to connect
if (client.connect(clientId.c_str())) {
Serial.println("connected");
// Once connected, publish an announcement...
client.publish("outTopic", "hello world");
// ... and resubscribe
client.subscribe("inTopic");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(1000);
}
}
}
void setup() {
pinMode(BUILTIN_LED, OUTPUT); // Initialize the BUILTIN_LED pin as an output
Serial.begin(115200);
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
}
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
long now = millis();
if (now - lastMsg > 2000) {
lastMsg = now;
++value;
snprintf (msg, 50, "hello world #%ld", value);
Serial.print("Publish message: ");
Serial.println(msg);
client.publish("outTopic", msg);
}
}
Screenshots:
1) netstat -tulpn | grep LISTEN
2) ioBrocker log
3) Arduino IDE
UPDATE:
I did not find where you can change or disable listen port 1883 tcp6.
But I managed to establish a connection between the devices by replacing the Mikrotik router with Keenetic.
Now we need to figure out what's wrong with the settings of the router.
Your screenshot:
shows that ioBroker is listening on the IPv4 loopback interface (127.0.0.1) for ports 9000 and 9001, and on a tcp6 (IPv6) interface for ports 8081, 8082 and 1883.
That means it's only reachable via IPv4 from programs running on the same server as it, or from programs running on computers capable of speaking IPv6.
The ESP8266 is not capable of speaking IPv6.
You need to reconfigure ioBroker to listen on 0.0.0.0:mqtt so that IPv4 software can reach it.
I am using UDP to connect two nodemcu modules. One nodemcu is wireless acces point and another nodemcu connects to access point as client.
This code sends client's IP adress to AP when client connects:
Udp.beginPacket("192.168.4.1", UDPPort);//send ip to server
char ipBuffer[20];
WiFi.localIP().toString().toCharArray(ipBuffer, 20);
Udp.write(ipBuffer);
Udp.endPacket();
Serial.println("Sent ip adress to server");
But on the server side I don't recieve this packet.
Client:
#include <ESP8266WiFi.h>
#include <WiFiUDP.h>
unsigned int UDPPort = 2390; // local port to listen on
char packetBuffer[255]; //buffer to hold incoming packet
char replyBuffer[] = "acknowledged"; // a string to send back
WiFiUDP Udp;
void setup() {
Serial.begin(115200);
WiFi.begin("Wi-Fi");
Serial.println();
Serial.print("Wait for WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: " + WiFi.localIP().toString());
Udp.begin(UDPPort);
Udp.beginPacket("192.168.4.1", UDPPort);//send ip to server
char ipBuffer[255];
WiFi.localIP().toString().toCharArray(ipBuffer, 255);
Udp.write(ipBuffer);
Udp.endPacket();
Serial.println("Sent ip adress to server");
}
void loop() {
// if there's data available, read a packet
int packetSize = Udp.parsePacket();
if (packetSize) {
Serial.print("Received packet of size ");
Serial.println(packetSize);
Serial.print("From ");
IPAddress remoteIp = Udp.remoteIP();
Serial.print(remoteIp);
Serial.print(", port ");
Serial.println(Udp.remotePort());
// read the packet into packetBufffer
int len = Udp.read(packetBuffer, 255);
if (len > 0) {
packetBuffer[len] = 0;
}
Serial.println("Contents:");
Serial.println(packetBuffer);
// send a reply, to the IP address and port that sent us the packet we received
Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
Udp.write(replyBuffer);
Udp.endPacket();
}
}
Server:
#include <ESP8266WiFi.h>
#include <WiFiUDP.h>
unsigned int UDPPort = 2390; // local port to listen on
char packetBuffer[255]; //buffer to hold incoming packet
char ReplyBuffer[] = "acknowledged"; // a string to send back
WiFiUDP Udp;
void setup() {
Serial.begin(115200);
WiFi.softAP("Wi-Fi");
Udp.begin(UDPPort);
Serial.println();
Serial.println("Started ap. Local ip: " + WiFi.localIP().toString());
}
void loop() {
// if there's data available, read a packet
int packetSize = Udp.parsePacket();
if (packetSize) {
Serial.print("Received packet of size ");
Serial.println(packetSize);
Serial.print("From ");
IPAddress remoteIp = Udp.remoteIP();
Serial.print(remoteIp);
Serial.print(", port ");
Serial.println(Udp.remotePort());
// read the packet into packetBufffer
int len = Udp.read(packetBuffer, 255);
if (len > 0) {
packetBuffer[len] = 0;
}
Serial.println("Contents:");
Serial.println(packetBuffer);
// send a reply, to the IP address and port that sent us the packet we received
Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
Udp.write(ReplyBuffer);
Udp.endPacket();
}
}
Another thing doesn't work: If I send a packet from another device connected to AP nodemcu to client nodemcu(also connected to AP), packet is recieved, but I get no acknowledgement reply back to device.
Everything else works - If i send a packet from another device to AP nodemcu, packet is recieved and i get acknowledgement.
Also, if I connect to my home wi-fi router with client nodemcu and listen for packet from my pc, i get client's ip adress when it connects.
I got exactly the same problem. I've just solve it. Your code is almost the same as mine.
All ESP- modules can be AP and station.
That means, a ESP module has local network for itself.
In my case, client module(ESP) is station mode and server module(ESP) is SoftAP mode.
The ip of the server module is 192.168.4.9 and I set the ip of gateway is 192.168.4.1.
When client module connected to the AP of server module, the ip of client was 192.168.4.103, and then i tried to send udp packets from the client module to the AP. Nothing happened but when i send the same packet from other device such as pc it worked.
I tried to access the AP of server module on my laptop. I found a wired SSID the name was 'EPS_4510DB'. It was actually the client module's one. The gateway ip of ESP_4510DB was 192.168.4.1.
Suddenly I realised the network of client module's AP and of server module's AP is the same, and the client module(for station)'s network linked its own AP network.
In other word, the client module sent udp packets to AP's network of itself instead of one of the server module.
So i changed the ip and i was able to send udp packets to server module.
And as #Barry Bea mentioned, I think you can also disable the AP of client module by using WiFi.mode(WIFI_STA) in client module, not server module.
I hope it helps someone~
I had to change port numbers for each conected esp8266. If IP of esp was 192.168.4.2, I set port to 2302, for 192.168.4.3, I set it to 2303...
I have painstakingly been trying to trouble shoot a similar problem...
I too could not get any packages sent by my ESP8266's
I changed your line;
WiFi.softAP("Wi-Fi");
to ....
WiFi.mode(WIFI_STA);
works EVERY TIME now....with no package loss..
I'm trying to send information from the arduino board to my computer through the Wi-Fi network.
for my project's purposes it has to be a UDP connection
I use the "Send and Receive UDP String" example (http://arduino.cc/en/Tutorial/WiFiSendReceiveUDPString)
with a few changes:
#include <SPI.h>
#include <WiFi.h>
#include <WiFiUdp.h>
int status = WL_IDLE_STATUS;
char ssid[] = "itay_net"; // your network SSID (name)
char pass[] = "0527414540"; // your network password (use for WPA, or use as key for WEP)
unsigned int localPort = 50505; // local port to listen on
IPAddress remote_ip(192, 168, 1, 100);
unsigned int remote_port = 50505;
char ReplyBuffer[] = "acknowledged"; // a string to send back
WiFiUDP Udp;
void setup() {
//Initialize serial and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
// check for the presence of the shield:
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
// don't continue:
while(true);
}
// attempt to connect to Wifi network:
while ( status != WL_CONNECTED) {
Serial.print("Attempting to connect to WPA SSID: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network:
status = WiFi.begin(ssid, pass);
// wait 10 seconds for connection:
delay(10000);
}
// you're connected now, so print out the data:
Serial.print("You're connected to the network");
delay(10000);
printWifiStatus();
Serial.println("\nStarting connection to server...");
// if you get a connection, report back via serial:
Udp.begin(localPort);
}
void loop() {
int bite_send;
Udp.beginPacket(remote_ip, remote_port);
bite_send = Udp.write("hello");
Udp.endPacket();
Serial.println("the packet was sent");
Serial.println(bite_send);
delay(1000);
}
void printWifiStatus() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print your WiFi shield's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
}
It compiles and connects to the network just fine.
the only problem is that I can't tell if the packet was sent because I see no trace of it on Wireshark.
I also wrote a socket on java that listens to the port (50505) and should display the message from the packet, but it didn't work either.
(I can copy the java code here but i can assure you that it is not the problem 'cause I tested it with a different java server and it worked, so the problem should be on the Arduino side)
a few details to narrow it down:
I believe the "remote ip" is correct but even if it isn't - I still should have seen it in the Wireshark, so it can't be the problem.
I should mention that the Wi-Fi shield works, I successfully sent pings and ran other examples (such as SimpleWebServerWifi).
I'm using an original Arduino Uno R3 board and an original Wi-Fi shield.
The arduino IDE is the newest version.
I updated the Wi-Fi shield with the newest update I found on GitHub.
I also ran the same "Send and Receive UDP String" code (with the necessary changes) on my Ethernet shield and it did work.
I don't know what else to try - please help.
any help will be appreciated.
Itay
I dont think you have a reply buffer packet. google arduino wifisendrecieve and you will see the example they have that has a reply packet labeled as 'acknowledged'. Hope this helps