Home | pfodApps/pfodDevices | WebStringTemplates | Java/J2EE | Unix | Torches | Superannuation | CRPS Treatment | | About Us
 

Forward Logo (image)      

Multiple Connections to ESP32 pfodDevice™
How to code ESP32 to allow more than on pfodApp™ to connect at the same time

by Matthew Ford 1st Feb 2024 (originally posted 1st Feb 2024)
© Forward Computing and Control Pty. Ltd. NSW Australia
All rights reserved.

Multi-connections to ESP32 WiFi pfodDevice

Introduction
(Note: This tutorial needs pfodParser library V3.63.1+ (available from the Arduino library manager) and the pfodESP32BufferedClient library (zip file)

ESP32 is a low cost dual processor chip, with support for WiFi, Bluetooth Classic and BLE (Bluetooth Low Energy). pfodDesignerV3 is WYSIWYG (what-you-see-is-what-you-get) Android App that lets you design menus and charts and then generated the code for the ESP32, as a pfodDevice, so that pfodApp can connect is display the menus and charts you designed.

pfodApp only connects to one pfodDevice at a time and typically a pfodDevice is designed to only allow one connection at a time. However if the pfodDevice primarily displays readings, like temperature/humidity for example, than can be convenient to allow multiple pfodApps to connect at the same and display the readings on multiple Android mobiles/tablets.

This tutorial shows how to modify the ESP32 WiFi code generated by the free pfodDesignerV3 Android app to allow for multiple connections as the same time.

Parts List (as at 1st Dec 2023 excluding shipping)

Basic
Sparkfun ESP32 Thing ~US$25.50
ESP32 Arduino package V2.0.11 install via Arduino Boards Manager
SafeString library V4.1.30 installed via Arduino Library Manager
pfodParser library V3.63.1 installed via Arduino Library Manager
pfodESP32BufferedClient.zip library
ESPAutoWiFiConfig library installed via Arduino Library Manager

pfodDesignerV3, free Android app for designing pfodApp menus and charts for controlling your project
pfodApp ~US$12 Android app to display those menus and charts and to log the data.

Creating a simple menu for the ESP32

Install pfodDesignerV3 on your Android mobile and design a simple control to vary the led as shown in this ESP32 Code Generator for pfodApp tutorial with one small change.
Set the
Refresh Interval 5 secs using the slider, as shown here. Note also the Target ESP32 via WiFi setting.

Then generate the code for ESP32 via WiFi. Save it to a file and import it to Arduino.
ESP32_Led.ino contains the generated code.

Setting up Arduino for ESP32 and pfodApp

Install the ESP32 support for Arduino 1.8.19+ by following these instructions Installing using Arduino IDE (note in the Arduino Board Manager select the ESP32 by Espressif System package) Here the ESP32 board support V2.0.14 was used.

Use the Arduino library manager, install the pfodParser library (V3.63.1 or higher) (i.e. Tools → Manage Libraries.. and type in pfodParser into the search bar)
Download the
pfodESP32BufferedClient.zip library and install it using Sketch → Include Library → Add .ZIP library..

Testing the single connection sketch

Edit ESP32_Led.ino to set your networks SSID and password and to choose an IP for this device. e.g. const char staticIP[] = “10.1.1.71”;
Leave the
pfodSecurityCode empty.

Install pfodApp and set up a connection for WiFi with the IP you set and port 4989. See the pfodAppForAndroidGettingStarted.pdf
Connect and move the slider to change the Led brightness.

Modifying the Sketch to support Multiple Connections

The final modified sketch is ESP32_Led_Multi.ino

The modifications made to the base ESP32_Led.ino are as follows:-
At the top of the sketch add

const uint8_t MAX_CLIENTS = 4; // the default
WiFiClient clients[MAX_CLIENTS]; // hold the currently open clients
pfodParser *parserPtrs[MAX_CLIENTS]; // hold the parsers for each client
pfodESP32BufferedClient *bufferedClientPtrs[MAX_CLIENTS]; // hold the parsers for each client

bool validClient(WiFiClient &client) {
  return (client.connected());
}

At the top of setup() initialise these

void setup() {
  // always have at least one
  parserPtrs[0] = &parser;
  bufferedClientPtrs[0] = &bufferedClient;

  // fill in the rest
  for (size_t i = 1; i < MAX_CLIENTS; i++) {
    parserPtrs[i] = new pfodParser(parser.getVersion());
    bufferedClientPtrs[i] = new pfodESP32BufferedClient();
  }
. . . 

Move the parser processing into its own method and pass the parser to the sendMainMenu(parser) and sendMainMenuUpdate(parser) method calls

void handle_pfodParser(pfodParser &parser) {
    uint8_t cmd = parser.parse(); // parse incoming data from connection
    // parser returns non-zero when a pfod command is fully parsed
    if (cmd != 0) { // have parsed a complete msg { to }
. . .
}

Replace loop() with

void loop() {
 if (server.hasClient()) { // new connection
#ifdef DEBUG
    Serial.print("new client:");
#endif
    bool foundSlot = false;
    size_t i = 0;
    for (; i < MAX_CLIENTS; i++) {
      if (!validClient(clients[i])) { // this space if free
        foundSlot = true;
        clients[i] = server.available();
        parserPtrs[i]->connect(bufferedClientPtrs[i]->connect(&(clients[i]))); // sets new io stream to read from and write to
        break;
      }
    }
    if (!foundSlot) {
      WiFiClient newClient = server.available(); // get any new client and close it
      newClient.stop();
#ifdef DEBUG
      Serial.println(" NO Slots available");
#endif
    } else {
#ifdef DEBUG
      Serial.println(i);
#endif
    }
  }
  for (size_t i = 0; i < MAX_CLIENTS; i++) {
    if (validClient(clients[i])) {
      handle_pfodParser(*parserPtrs[i]);
    }
  }
}

Replace closeConnection() with

void closeConnection(Stream *io) {
  if (!io) {
#ifdef DEBUG
    Serial.println("closeConnection: Connection stream NULL");
#endif
    return;
  }
#ifdef DEBUG
  Serial.print("closeConnection:");
#endif
  bool foundSlot = false;
  size_t i = 0;
  for (; i < MAX_CLIENTS; i++) {
    if ((parserPtrs[i]->getPfodAppStream() == io) && validClient(clients[i])) {
      foundSlot = true;
      break;
    }
  }
  if (foundSlot) {
#ifdef DEBUG
    Serial.println(i);
#endif
    // found match
    parserPtrs[i]->closeConnection(); // nulls io stream
    bufferedClientPtrs[i]->stop(); // clears client reference
    clients[i].stop();
  } else {
#ifdef DEBUG
    Serial.println(" Connection stream NOT found");
#endif
  }
}

Add the parser argument to the sendMainMenu(pfodParser &parser) and sendMainMenuUpdate(pfodParser &parser).

void sendMainMenu(pfodParser &parser) {
. . .
}

void sendMainMenuUpdate(pfodParser &parser) {
. . .
}

Testing Multiple Connections

Set your network's SSID and password and an IP address in ESP32_Led_Multi.ino and then program the ESP32 board.
Open a pfodApp connection from one mobile and check the Led brightness can be controlled.
Then open a second pfodApp connection from another mobile and see that the slider % reflects the current setting.
Adjust the Led brightness from either mobile and the other one will update when the menu refreshes (less than 5sec delay)

For a more extensive example see the Solar Hot Water Monitor code that includes graphical elements. Note: Only the Monitor allows multiple connections, the Solar Hot Water pfodDevice which controls the hot water is one connection at a time.

Conclusion

This tutorial has shown how to modify the code generated by pfodDesigner to allow for multiple mobiles to connect to the one pfodDevice. This is typically used then displaying measurements at multiple locations.



AndroidTM is a trademark of Google Inc. For use of the Arduino name see http://arduino.cc/en/Main/FAQ


The General Purpose Android/Arduino Control App.
pfodDevice™ and pfodApp™ are trade marks of Forward Computing and Control Pty. Ltd.






Forward home page link (image)

Contact Forward Computing and Control by
©Copyright 1996-2024 Forward Computing and Control Pty. Ltd. ACN 003 669 994