ESP8266-12 AP with multiple ESP8266-12 STA

Hi All

I'm running the above combination of AP (station) & STA (client) & receive the following:

Received from client0 (IP/Size/Data): 192.168.4.2 / 33 / Sending to AP from client1 25'C

Connected to WiFi.localIP 0.0.0.0 WiFi.softAPIP 192.168.4.1

Received from client0 (IP/Size/Data): 192.168.4.3 / 37 / Send millis from client2: 10314294

Connected to WiFi.localIP 0.0.0.0 WiFi.softAPIP 192.168.4.1

Received from client0 (IP/Size/Data): 192.168.4.2 / 33 / Sending to AP from client1 25'C

Connected to WiFi.localIP 0.0.0.0 WiFi.softAPIP 192.168.4.1

Received from client0 (IP/Size/Data): 192.168.4.3 / 37 / Send millis from client2: 10316295

Connected to WiFi.localIP 0.0.0.0 WiFi.softAPIP 192.168.4.1

I need to be able to identify & store the incoming data from each STA for processing by a mega2560 which has the ESP8266-12 AP attached but all my attempts have failed.

Is there a way to use the STA IP addresses as a pointer to the data so as to get:

Received from client1 (IP/Size/Data): 192.168.4.2 / 33 / Sending to AP from client1 25'C

Received from client2 (IP/Size/Data): 192.168.4.3 / 37 / Send millis from client2: 10314294

thereby identifying the source of the data as client1 or client2 not both as client0

I've tried strcmp(port.remoteIP(), "192.168.4.2") but that doesn't compile, with the error:

invalid user-defined conversion from 'IPAddress' to 'const char*' [-fpermissive]

I've attched the 3 sketches (1 AP & 2 STA) in the hope someone can help

MyAdafruitFeatherSTA_9-7-16_3.ino (2 KB)

MyAdafruitHuzzahSTA_9-7-16_3.ino (3.81 KB)

MyAdafruitFeatherAP_9-7-16_1.ino (2.4 KB)

I'm running the above combination of AP (station) & STA (client) & receive the following:

Just from a terminology perspective:

AP = Access Point (build a wifi network and handle connexions)
STA = Station (client of a wifi network)

On the client side you might want to call WiFi.mode(WIFI_STA);

On the server side, in the loop:

You check for the presence of a UDP packet int packetSize = port.parsePacket();. that returns the size of a received UDP packet but that does not read the packet itself.

Then you move straight to

  if (strcmp ([color=red]IPclient1[/color], "192.168.4.2") == 0 && packetSize == 6)                  //compares char IPclient[] to IP address received from client

is not working there for 2 reasons:

1/ error in your testing approach
Because you are testing your IPclient1 which will always be == "192.168.4.2" because that's what you initialized it with. what you probably want to do is compare the IP of the client with "192.168.4.2" to see if it's the first one. The IP of the client you can get with port.remoteIP() but you can't purely compare that with "192.168.4.2" because port.remoteIP() returns 4 bytes which represent the IP address of the remote connection.

You could declare your IPClient as such

IPAddress IPclient1(192, 168, 4, 2); instead of char IPclient1[] = "192.168.4.2";

the IPAddress class implements the == operator, so you can directly check for equality port.remoteIP() with an IPAddress instance.

2/ you can't do that testing at that time.

because port.parsePacket() actually did not read the packet itself. yet. So you only want to do your client comparison within your block

  if (packetSize)  {
    int len = port.read(packetBuffer, 255);
    if (len > 0) packetBuffer[len - 1] = 0;
...

at that point you are sure to have a client and you are sure you have read it's communication

Thanks for the help J-M-L

Managed to get the 2 clients Tx'ing the data in a format I can use for processing by the Mega2560 using your suggestions.

For anyone who is interested, this project allows me to use multiple ESP8266-12 clients (STA) to create home central heating 'zones' that wirelessly transmit room temperatures to the ESP8266-12 Access point (AP).
This data is used to control the 'firing' of the gas boiler based on demand from the 'zones' rather than just the 1 zone I have at present.

I have 8 Max! EQ-3 wireless thermostatic radiator valves but found that the data they produce is not suitable for controlling gas boiler firing.

I have attached the sketches I currently use (I'm testing the use of 2 clients for now but plan to increase this to 4 clients in the near future.

This is a snapshot of the serial monitor output from the AP from data sent from the 2 clients:

Received from client(IP/Size/Data): 192.168.4.2 / 4 / 50
data received from client1
packetBuffer1 = 50

integer client1Temp = 50 //this is the data used by the Mega2560

Connected to WiFi.localIP 0.0.0.0 WiFi.softAPIP 192.168.4.1

Received from client(IP/Size/Data): 192.168.4.3 / 4 / 25
data received from client2
packetBuffer2 = 25

integer client2Temp = 25 //this is the data used by the Mega2560

Connected to WiFi.localIP 0.0.0.0 WiFi.softAPIP 192.168.4.1

I hope this info is useful for anyone interested in 'home automation'

MyAdafruitFeatherAP_10-7-16_5.ino (4.56 KB)

MyAdafruitHuzzahSTA_10-7-16_5.ino (3.66 KB)

MyAdafruitFeatherSTA_10-7-16_5.ino (1.57 KB)

Great to hear that helped

Cool project

To the above project I've added additional data to be sent from each client namely relative humidity. Each data packet now contains integer temperature (T) data & integer releative humidity (RH) data but I'm struggling to separate these 2 bits of data contained within the packetBuffer received at the Access Point (AP).

I tried this mod to the AP sketch but can't get it to work:

if (port.remoteIP() == IPClient2) //IP address = 192,168,4,3
{
clientNumber = 2;
Serial.print("\ndata received from client");
Serial.println(clientNumber);
Serial.print("packetBuffer2 = ");
Serial.println(packetBuffer);

commandT[1] = packetBuffer[0];
commandT[2] = packetBuffer[1];
commandT[3] = '\0';

client2Temp = atoi(packetBuffer);
Serial.print("integer client2Temp = ");
Serial.println(client2Temp);

commandRH[1] = packetBuffer[3];
commandRH[2] = packetBuffer[4];
commandRH[3] = '\0';

client2RH = atoi(packetBuffer);
Serial.print("integer client2RH = ");
Serial.println(client2RH);
}

Any suggestions would be welcomed

      commandT[[color=red]1[/color]] = packetBuffer[0];
      commandT[[color=red]2[/color]] = packetBuffer[1];
      commandT[[color=red]3[/color]] = '\0';
      
      client2Temp = atoi([color=red]packetBuffer[/color]);
      Serial.print("integer client2Temp = ");
      Serial.println(client2Temp);

      commandRH[[color=red]1[/color]] = packetBuffer[[color=blue]3[/color]];
      commandRH[[color=red]2[/color]] = packetBuffer[[color=blue]4[/color]];
      commandRH[[color=red]3[/color]] = '\0';
      
      client2RH = atoi([color=red]packetBuffer[/color]);
      Serial.print("integer client2RH = ");
      Serial.println(client2RH);

I highlighted some possible obvious issues

what is in packetBuffer[2]; why do you skip it? (you read 0,1 and then 3,4)

Additional question I would have is "did you send the T° and the Humidity% as ASCII or just the integer value one 2 Bytes?"

what is in packetBuffer[2]; why do you skip it? (you read 0,1 and then 3,4)

that was a typo!
It should have been:

commandRH[1] = packetBuffer[2];
commandRH[2] = packetBuffer[3];

did you send the T° and the Humidity% as ASCII or just the integer value

I use just integer values for both T & RH.

My thinking was that the packetBuffer from the client held the 2 integer values for T & RH ie

packetBuffer[0];
packetBuffer[1]; hold the 2 integer value of T &

packetBuffer[2];
packetBuffer[3]; hold the 2 integer value of RH

the array commandT[] extracts the 2 T integers in:

commandT[1] = packetBuffer[0];
commandT[2] = packetBuffer[1];

similarly for RH

Is this assumption valid?

if you sent them with print, then they arrive as ASCII.
if you sent them with a write, then they arrived as binary

7° in ASCI is just 1 byte
22° in ASCII is 2 bytes

so the print in ASCII won't guarantee the size.

if you sent them with a write, then you need to do some bit operation to stuff packetBuffer[0]; and packetBuffer[1]; as the high part and low part of an int --> no need to mess around with char arrays, no atoi(), etc

makes sense?